C# 从Moq模拟集获取IQueryable

C# 从Moq模拟集获取IQueryable,c#,entity-framework,unit-testing,moq,C#,Entity Framework,Unit Testing,Moq,我尝试使用实体框架和Moq模拟我的上下文来测试我的存储库 我当前在测试我的存储库中的GetSingle查询时遇到问题: public Customer GetSingle(int id, HotelBookingContext context = null, params Expression<Func<Customer, object>>[] navigationProperties) { using (var tempContext = context ??

我尝试使用实体框架和Moq模拟我的上下文来测试我的存储库

我当前在测试我的存储库中的
GetSingle
查询时遇到问题:

public Customer GetSingle(int id, HotelBookingContext context = null, params Expression<Func<Customer, object>>[] navigationProperties)
{
    using (var tempContext = context ?? new HotelBookingContext())
    {
        IQueryable<Customer> dbQuery = tempContext.Set<Customer>();

        foreach (Expression<Func<Customer, object>> navigationProperty in navigationProperties)
            dbQuery = dbQuery.Include(navigationProperty);

        return dbQuery
                .AsNoTracking()
                .FirstOrDefault(x => x.Id == id);
    }
}
public Customer GetSingle(int-id,HotelBookingContext-context=null,params-Expression[]navigationProperties)
{
使用(var tempContext=context??新建HotelBookingContext())
{
IQueryable dbQuery=tempContext.Set();
foreach(navigationProperties中的表达式navigationProperty)
dbQuery=dbQuery.Include(navigationProperty);
返回数据库查询
.AsNoTracking()
.FirstOrDefault(x=>x.Id==Id);
}
}
使用以下测试:

public void GetSingle_QueryingASingleCustomer_ReturnsASingleCustomer()
{
    var cus = new Customer() { Email = "testMail", Name = "testName", Id = 1 };
    var customer = new List<Customer> {cus}.AsQueryable();

    var mockSet = new Mock<DbSet<Customer>>();
    mockSet.As<IQueryable<Customer>>().Setup(m => m.Provider).Returns(customer.Provider);
    mockSet.As<IQueryable<Customer>>().Setup(m => m.Expression).Returns(customer.Expression);
    mockSet.As<IQueryable<Customer>>().Setup(m => m.ElementType).Returns(customer.ElementType);
    mockSet.As<IQueryable<Customer>>().Setup(m => m.GetEnumerator()).Returns(customer.GetEnumerator());

    var mockContext = new Mock<HotelBookingContext>();
    mockContext.Setup(m => m.Customers).Returns(mockSet.Object);

    var temp = _customerRepository.GetSingle(cus.Id, mockContext.Object);
    Assert.AreEqual(temp.Name, cus.Name);
    Assert.AreEqual(temp.Email, cus.Email);
    Assert.AreEqual(temp.Id, cus.Id);
}
public void GetSingle\u queryingasingcustomer\u ReturnsASingleCustomer()
{
var cus=new Customer(){Email=“testMail”,Name=“testName”,Id=1};
var customer=新列表{cus}.AsQueryable();
var mockSet=new Mock();
mockSet.As().Setup(m=>m.Provider).Returns(customer.Provider);
mockSet.As().Setup(m=>m.Expression)。返回(customer.Expression);
mockSet.As().Setup(m=>m.ElementType).Returns(customer.ElementType);
mockSet.As().Setup(m=>m.GetEnumerator()).Returns(customer.GetEnumerator());
var mockContext=new Mock();
Setup(m=>m.Customers).Returns(mockSet.Object);
var temp=_customerRepository.GetSingle(cus.Id,mockContext.Object);
Assert.AreEqual(临时名称、客户名称);
Assert.AreEqual(临时电子邮件、客户电子邮件);
Assert.AreEqual(临时Id、客户Id);
}
如果调试代码,我会注意到在
GetSingle
函数中,调用
dbQuery
IQueryable
保持
null
,因此不能在return语句中使用

为什么会这样


但是,如果我在真实的上下文中运行它,它可以正常工作。

这是因为在安装程序中,您在模拟上下文上设置了
.Customers
属性,而不是
.Set()
函数。根据目前的设置,Moq不知道该怎么办

mockContext.Setup(m => m.Set<Customer>()).Returns(mockSet.Object);
…然后您需要将测试中的方法更新为

IQueryable<Customer> dbQuery = tempContext.Customers;
IQueryable dbQuery=tempContext.Customers;

这是因为在设置中设置了
.Customers
属性,而不是
.Set()
函数。根据目前的设置,Moq不知道该怎么办。
IQueryable<Customer> dbQuery = tempContext.Customers;