我正在尝试为我们的存储库/工作单元框架设置单元和集成测试。模拟查询工作正常,直到引入导航属性。以下工作正常:
var customers = (from cus in Customers.GetAll()
join acm in AccountManagers.GetAll() on cus.INS_Id equals acm.INS_Id
join the in Employees.GetAll() on acm.THE_Id equals the.THE_Id
select new CustomerModel()
{
Id = cus.INS_Id,
Name = cus.INS_Name,
OrganizationNumber = cus.INS_OrgNo,
PostalAddress = cus.INS_PostalAddress1,
PostalCity = cus.INS_PostalCity,
...
但是,在这样的选择中添加一行不起作用:
var customers = (from cus in Customers.GetAll()
join acm in AccountManagers.GetAll() on cus.INS_Id equals acm.INS_Id
join the in Employees.GetAll() on acm.THE_Id equals the.THE_Id
select new CustomerModel()
{
Id = cus.INS_Id,
Name = cus.INS_Name,
OrganizationNumber = cus.INS_OrgNo,
PostalAddress = cus.INS_PostalAddress1,
PostalCity = cus.INS_PostalCity,
Brokered = cus.InsuredBrokers.Any(),
...
原因是cus.InsuredBrokers
是导航属性,而Moq不知道如何处理它。
我已经设置了这样的测试:
// Sets up a new Mock DbSet, given a list of inmemory data
private Mock<DbSet<T>> SetupSet<T>(IQueryable<T> data) where T : class
{
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
return mockSet;
}
// Sets up a new Mock DbContext with a given Mock DbSet of data
private Mock<PrositContext> SetupContext<T>(Mock<DbSet<T>> set) where T : class
{
var mockContext = new Mock<PrositContext>();
mockContext.Setup(m => m.Set<T>()).Returns(set.Object);
return mockContext;
}
// Adds a given Mock DbSet of data to an existing Mock DbContext
private Mock<PrositContext> SetupContext<T>(Mock<DbSet<T>> set, Mock<PrositContext> existingContext) where T : class
{
existingContext.Setup(m => m.Set<T>()).Returns(set.Object);
return existingContext;
}
// Sets up a new Mock DbContext given a list of inmemory data
private Mock<PrositContext> SetupContext<T>(IQueryable<T> data) where T : class
{
var mockSet = SetupSet(data);
return SetupContext(mockSet);
}
// Adds to an existing Mock DbContext a list of inmemory data
private Mock<PrositContext> SetupContext<T>(IQueryable<T> data, Mock<PrositContext> existingContext) where T : class
{
var mockSet = SetupSet(data);
return SetupContext(mockSet, existingContext);
}
[TestMethod]
public void TestGetCustomerName()
{
// ARRANGE
// Read the data from a .csv file
var customerData = new CsvCustomerRepository(null).GetAll();
var accountManagerData = new CsvAccountManagerRepository(null).GetAll();
var employeeData = new CsvTHEmployeeRepository(null).GetAll();
var nrsData = new CsvNordicRiskSolutionsRepository(null).GetAll();
var inbData = new CsvInsuredBrokersRepository(null).GetAll();
var gsiData = new CsvGeneralSystemInfoRepository(null).GetAll();
// Setup the mock context with all the data from the .csv
var mockContext = SetupContext(customerData);
SetupContext(accountManagerData, mockContext);
SetupContext(employeeData, mockContext);
SetupContext(nrsData, mockContext);
SetupContext(inbData, mockContext);
SetupContext(gsiData, mockContext);
var customerFacade = new CustomerFacade(mockContext.Object);
// ACT
var customers = customerFacade.GetByNameMOCKFORTESTING("Bos");
// ASSERT
//Assert.AreEqual(...);
}
public IEnumerable<ICustomerModel> GetByNameMOCKFORTESTING(string name)
{
var customers = (from cus in Customers.GetAll()
join acm in AccountManagers.GetAll() on cus.INS_Id equals acm.INS_Id
join the in Employees.GetAll() on acm.THE_Id equals the.THE_Id
where cus.INS_Name.Contains(name)
select new CustomerModel()
{
Id = cus.INS_Id,
Name = cus.INS_Name,
OrganizationNumber = cus.INS_OrgNo,
PostalAddress = cus.INS_PostalAddress1,
PostalCity = cus.INS_PostalCity,
Brokered = cus.InsuredBrokers.Any(),
CustomerResponsible = new THEmployeeModel()
{
FirstName = the.THE_FirstName,
LastName = the.THE_LastName,
PhoneNumber = null
},
RiskClass = cus.INS_RiskKlass,
}).Take(300).ToList();
return customers;
}
我需要做些什么来模拟cus.InsuredBrokers
?我发现的示例,视频和教程没有涉及导航属性的主题,即使它们是常用的......
答案 0 :(得分:0)
模拟实体框架非常困难。即使您成功模拟了导航属性,那么使用延迟加载的序列或代码也是如此。你最终会为你的测试编写大量的模拟设置。
我们遇到了类似的问题,并使用Effort解决了这个问题,是内存数据库的EF提供程序。您可以为测试设置数据库,只需要模拟工作单元的创建。