Tôi đang sử dụng Web Api OData v4 trên máy chủ và OData Client code generator trên máy khách. Nó hoạt động tốt, nhưng tôi không biết làm thế nào để kiểm tra mã trên máy khách.Làm thế nào để kiểm tra đơn vị OData Client?
Trên máy chủ, tôi hiển thị dbSet "Cấp độ".
Dưới đây là một đoạn mã trên máy khách:
public class LevelViewer
{
public virtual ODataContainer Container{get;set;} //t4 template generated
public LevelViewer(ODataContainer container=null)
{
if(container==null)
{
Container=new ODataContainer(new Uri("http://blabla"));
}
}
//I want to test this (actually there are more things, this is an example)
public List<Level> GetRootLevels()
{
return ODataContainer.Levels.Where(l=>l.IsRoot).ToList();
}
}
Tôi chấp nhận container OData tạo ra bởi các mẫu T4 như một tham số cho các nhà xây dựng để có thể Mock nó bằng cách nào đó.
Đơn vị kiểm tra, đây là nơi tôi đang mất:
[TestMethod]
public void LevelsVMConstructorTest()
{
List<Level>levels=new List<Level>();
levels.Add(new Level(){Id=1,LevelId=1,Name="abc",IsRoot=True});
IQueryable<Level>levelsIQ=levels.AsQueryable<Level>();
//?
var odataContainerMock=new Mock<ODataContainer>();
odataContainerMock.Setup(m=>m.Levels).Returns(I DON'T KNOW);
//I want to get here
LevelViewer lv = new LevelViewer(odataContainerMock.Object);
Assert.IsTrue(lv.GetRootLevels().Any());
}
Vì vậy, trong bài kiểm tra đơn vị này, tôi chỉ muốn kiểm tra logic bên trong phương pháp GetRootLevels, tôi không muốn thực hiện một thử nghiệm tích hợp hoặc một dịch vụ tự lưu trữ, tôi chỉ muốn thử nghiệm phương thức với dữ liệu trong bộ nhớ.
Làm cách nào để giả tạo lớp khách được tạo OData mà thực sự là lớp DataServiceContext?
Tôi đang sử dụng Moq, nhưng nó có thể được bất cứ điều gì, (miễn phí hoặc ít nhất có trong phiên bản chuyên nghiệp VS)
Edit: Đây là việc thực hiện các ODataContainer (nhớ này là autogenerated bởi OData client)
public partial class ODataContainer : global::Microsoft.OData.Client.DataServiceContext
{
/// <summary>
/// Initialize a new ODataContainer object.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
public ODataContainer(global::System.Uri serviceRoot) :
base(serviceRoot, global::Microsoft.OData.Client.ODataProtocolVersion.V4)
{
this.ResolveName = new global::System.Func<global::System.Type, string>(this.ResolveNameFromType);
this.ResolveType = new global::System.Func<string, global::System.Type>(this.ResolveTypeFromName);
this.OnContextCreated();
this.Format.LoadServiceModel = GeneratedEdmModel.GetInstance;
this.Format.UseJson();
}
partial void OnContextCreated();
/// <summary>
/// Since the namespace configured for this service reference
/// in Visual Studio is different from the one indicated in the
/// server schema, use type-mappers to map between the two.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
protected global::System.Type ResolveTypeFromName(string typeName)
{
global::System.Type resolvedType = this.DefaultResolveType(typeName, "WebServiceOData", "Constraint_Data_Feed.WebServiceOData");
if ((resolvedType != null))
{
return resolvedType;
}
resolvedType = this.DefaultResolveType(typeName, "DAL.Models", "Constraint_Data_Feed.DAL.Models");
if ((resolvedType != null))
{
return resolvedType;
}
return null;
}
/// <summary>
/// Since the namespace configured for this service reference
/// in Visual Studio is different from the one indicated in the
/// server schema, use type-mappers to map between the two.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
protected string ResolveNameFromType(global::System.Type clientType)
{
global::Microsoft.OData.Client.OriginalNameAttribute originalNameAttribute = (global::Microsoft.OData.Client.OriginalNameAttribute)global::System.Linq.Enumerable.SingleOrDefault(global::Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, typeof(global::Microsoft.OData.Client.OriginalNameAttribute), true));
if (clientType.Namespace.Equals("Constraint_Data_Feed.WebServiceOData", global::System.StringComparison.Ordinal))
{
if (originalNameAttribute != null)
{
return string.Concat("WebServiceOData.", originalNameAttribute.OriginalName);
}
return string.Concat("WebServiceOData.", clientType.Name);
}
if (clientType.Namespace.Equals("Constraint_Data_Feed.DAL.Models", global::System.StringComparison.Ordinal))
{
if (originalNameAttribute != null)
{
return string.Concat("DAL.Models.", originalNameAttribute.OriginalName);
}
return string.Concat("DAL.Models.", clientType.Name);
}
return null;
}
/// <summary>
/// There are no comments for Levels in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
[global::Microsoft.OData.Client.OriginalNameAttribute("Levels")]
public global::Microsoft.OData.Client.DataServiceQuery<global::Constraint_Data_Feed.DAL.Models.Level> Levels
{
get
{
if ((this._Levels == null))
{
this._Levels = base.CreateQuery<global::Constraint_Data_Feed.DAL.Models.Level>("Levels");
}
return this._Levels;
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
private global::Microsoft.OData.Client.DataServiceQuery<global::Constraint_Data_Feed.DAL.Models.Level> _Levels;
/// <summary>
/// There are no comments for Levels in the schema.
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
public void AddToLevels(global::Constraint_Data_Feed.DAL.Models.Level level)
{
base.AddObject("Levels", level);
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
private abstract class GeneratedEdmModel
{
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
private static global::Microsoft.OData.Edm.IEdmModel ParsedModel = LoadModelFromString();
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
private const string Edmx = @"<edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
<edmx:DataServices>
<Schema Namespace=""DAL.Models"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
<EntityType Name=""Level"">
<Key>
<PropertyRef Name=""Id"" />
</Key>
<Property Name=""Id"" Type=""Edm.Int32"" Nullable=""false"" />
<Property Name=""Name"" Type=""Edm.String"" Nullable=""false"" />
<Property Name=""LevelId"" Type=""Edm.Int32"" />
<NavigationProperty Name=""Sublevels"" Type=""Collection(DAL.Models.Level)"" />
<NavigationProperty Name=""Machines"" Type=""Collection(DAL.Models.Machine)"" />
</EntityType>
<EntityType Name=""Machine"">
<Key>
<PropertyRef Name=""Id"" />
</Key>
<Property Name=""Id"" Type=""Edm.Int32"" Nullable=""false"" />
<Property Name=""Name"" Type=""Edm.String"" Nullable=""false"" />
<Property Name=""LevelId"" Type=""Edm.Int32"" />
<NavigationProperty Name=""Level"" Type=""DAL.Models.Level"">
<ReferentialConstraint Property=""LevelId"" ReferencedProperty=""Id"" />
</NavigationProperty>
<NavigationProperty Name=""Parts"" Type=""Collection(DAL.Models.Part)"" />
</EntityType>
<EntityType Name=""Part"">
<Key>
<PropertyRef Name=""Id"" />
</Key>
<Property Name=""Id"" Type=""Edm.Int32"" Nullable=""false"" />
<Property Name=""Name"" Type=""Edm.String"" Nullable=""false"" />
<NavigationProperty Name=""Machines"" Type=""Collection(DAL.Models.Machine)"" />
</EntityType>
</Schema>
<Schema Namespace=""WebServiceOData"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
<EntityContainer Name=""ODataContainer"">
<EntitySet Name=""Levels"" EntityType=""DAL.Models.Level"">
<NavigationPropertyBinding Path=""Sublevels"" Target=""Levels"" />
</EntitySet>
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>";
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
public static global::Microsoft.OData.Edm.IEdmModel GetInstance()
{
return ParsedModel;
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
private static global::Microsoft.OData.Edm.IEdmModel LoadModelFromString()
{
global::System.Xml.XmlReader reader = CreateXmlReader(Edmx);
try
{
return global::Microsoft.OData.Edm.Csdl.EdmxReader.Parse(reader);
}
finally
{
((global::System.IDisposable)(reader)).Dispose();
}
}
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.4.0")]
private static global::System.Xml.XmlReader CreateXmlReader(string edmxToParse)
{
return global::System.Xml.XmlReader.Create(new global::System.IO.StringReader(edmxToParse));
}
}
}
Bạn có thể đảm bảo để không bao giờ nhận được một DefaultContainer rỗng kiểm tra các lớp học sử dụng constructor này. Và sau đó, thay đổi tham số để sử dụng một giao diện (IDefaultContainer hoặc một cái gì đó tương tự). Sau đó, bạn có thể kiểm tra GetRootLevels bằng cách so sánh đối tượng trả về là bất cứ điều gì bạn thiết lập trên lớp giả của bạn. – dcidral
Cảm ơn, tôi sẽ thử. – Tuco
Để làm việc đó, tôi phải giả lập thuộc tính Levels là một DataServiceQuery, chỉ có getter. Tôi vẫn đang suy nghĩ –
Tuco