[英]How do I mock multiple levels of DbSet.Include lambdas?
I'm using Moq to write unit tests that use Entity Framework 6 DbSet
and DbContext
objects. 我正在使用Moq编写使用Entity Framework 6
DbSet
和DbContext
对象的单元测试。 I have a service method with a cascading/multi-level Include
and I can't figure out how to set it up for testing. 我有一个带级联/多级
Include
的服务方法,我无法弄清楚如何设置它进行测试。 The service method looks something like this: 服务方法看起来像这样:
return DataContext.Cars
.Include(p => p.Model)
.Include(p => p.Model.Make)
.Select(c => new
{
Key = c.CarId,
Value = string.Format("{0} {1} {2}", c.Model.Make.Name, c.Model.Name, c.Trim)
}
).ToArray();
I know that I have to setup the Include
to return the mocked object, like this: 我知道我必须设置
Include
来返回模拟对象,如下所示:
mockCarDbSet.Setup(m => m.Include(It.IsAny<string>())).Returns(mockCarSet.Object);
But I'm getting a null reference exception from the cascaded .Include(p => p.Model.Make)
. 但我从级联的
.Include(p => p.Model.Make)
得到一个空引用异常。 How do I set up Moq to handle multiple levels of Include
? 如何设置Moq以处理多个级别的
Include
?
EDIT 编辑
OK, so it turns out that I can't use It.IsAny<string>
for Include
calls that use lambdas instead of strings, so now I have two problems: 好的,所以事实证明我不能使用
It.IsAny<string>
来进行使用lambdas而不是字符串的Include
调用,所以现在我有两个问题:
include()
is a static method(extension method). include()
是一个静态方法(扩展方法)。 Moq
doesn't support a static methods mock( read this link ). Moq
不支持静态方法mock( 阅读此链接 )。
To test your code you need to set your mockCarDbSet
to return IQueryable<Car>
: 要测试代码,您需要设置
mockCarDbSet
以返回IQueryable<Car>
:
var carQuery = new List<Car>
{
//add cars
}
IQueryable<Post> query = carQuery.AsQueryable();
return query
as a result of DataContext.Cars
作为
DataContext.Cars
的结果返回query
Those steps will work around the static method problem. 这些步骤将解决静态方法问题。
So thanks to @Old Fox reminding me that Moq won't work with static members, I found a way to do this using Microsoft Fakes. 所以感谢@Old Fox提醒我Moq不能与静态成员一起工作,我找到了一种方法来使用Microsoft Fakes。 Shims allows you to shim static methods.
垫片允许您填充静态方法。 I used Moq to set up
Mock<DbSet>
objects for each of the entities: 我使用Moq为每个实体设置
Mock<DbSet>
对象:
var carData = new List<Car>{new Car{ Trim = "Whatever" }};
var mockCarSet = new Mock<DbSet<Car>>();
mockCarSet.As<IQueryable<Car>>().Setup(m => m.Provider).Returns(carData.Provider);
mockCarSet.As<IQueryable<Car>>().Setup(m => m.Expression).Returns(carData.Expression);
mockCarSet.As<IQueryable<Car>>().Setup(m => m.ElementType).Returns(carData.ElementType);
mockCarSet.As<IQueryable<Car>>().Setup(m => m.GetEnumerator()).Returns(carData.GetEnumerator);
var mockMakeSet = new Mock<DbSet<Make>>();
//do the same stuff as with Car for IQueryable Setup
var mockModelSet = new Mock<DbSet<Model>>();
//do the same stuff as with Car for IQueryable Setup
using(ShimsContext.Create())
{
//hack to return the first, since this is all mock data anyway
ShimModel.AllInstances.MakeGet = model => mockMakeSet.Object.First();
ShimCar.AllInstances.ModelGet = car => mockModelSet.Object.First();
//run the test
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.