模拟包含具有最小起订量的导航属性的实体框架查询



我正在尝试为我们的存储库/工作单元框架设置单元和集成测试。在引入导航属性之前,模拟查询可以正常工作。以下工作正常:

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?我发现的示例、视频和教程没有涉及导航属性的主题,即使它们很常用......

模拟实体框架非常困难。即使成功模拟导航属性,使用延迟加载的序列或代码呢?您最终将为测试编写巨大的模拟设置。

我们遇到了类似的问题,并使用 Effort(内存中数据库的 EF 提供程序(解决了它。您可以为测试设置数据库,只需要模拟工作单元的创建。

最新更新