我在following way中设置了代码。我正在尝试测试一个方法,该方法只应在请求时加载一些相关的集合,它还会根据定义的参数过滤掉一些数据。如果我排除以下用于在对象上设置count属性的代码,我的测试就会通过:
类
public class Foo
{
public int Id {get; set;}
public ICollection<Bar> Bars {get; set;}
public int Count {get; set}
}
public class Bar
{
public int Id {get; set;}
public string Name {get; set;}
// ...
}
DbContext
..
public virtual DbSet<Foo> Foo {get;set;}
..
回购
public List<Foo> GetFoo(bool loadBar = false)
{
IEnumerable<Foo> foos = Context.Foo.AsEnumerable();
foreach (Foo f in foos)
{
// ...
if (loadBar)
{
Context.Entry(foo).Collection(c => c.Bars).Load();
}
foo.Count = Context.Entry(foo)
.Collection(c => c.Bars)
.Query() // <-- Throws InvalidOperationException
.Count();
// do some other filtering ...
return foos.ToList();
}
}
测试方法
[TestMethod]
public void Test()
{
Mock<DbContext> mockContext = new Mock<DbContext>();
Mock<DbSet<Foo>> fooMockSet = MockDbSet(new FooWithAtLeast1BarInCollection());
mockContext.Setup(c => c.Foo)
.Returns(fooMockSet.Object);
using(repo)
{
List<Foo> foos = repo.GetFoo();
}
}
public Mock<DbSet<T>> MockDbSet<T>(List<T> data) where T : class
{
var queryable = data.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
return dbSet;
}
当我运行代码时这很好用,但是当我收到以下异常时,我的模拟无法正确设置:
System.InvalidOperationException:无法为属性'CollectionToCount'调用成员'Query',因为{ParentType'}类型的实体 在上下文中不存在
如何设置Moq以便这样做?到目前为止我有这个,但我不确定它应该返回什么:
mockContext.Setup(x =>
x.Entry(It.IsAny<T>())
.Collection(c => c.CollectionToCount))
.Returns(???);