我正在使用模拟的IQueryable
(使用Moq)设置测试,我想在调用.Where()
时返回自己:
[SetUp]
public void Setup() {
mockPocos = new Mock<IQueryable<Poco>>();
mockPocos.Setup(foo => foo.Where(It.IsAny<Expression<Func<Poco, bool>>>()))
.Returns(mockPocos.Object);
}
(这样,我可以模拟像.Count
这样的方法/属性,并且知道无论被测试的方法在IQueryable
上运行查询多少次,它都会返回我可以控制的值。)
这个编译,但是当我运行它时,我得到了这个例外:
Tests.PocoTest.TestPocoQueryable:
SetUp : System.NotSupportedException : Expression references a method that does not belong to the mocked object: foo => foo.Where<Poco>(It.IsAny<Expression`1>())
我怎样才能让它发挥作用?
编辑:在回应评论时,这就是我想像这样使用Moq的原因。
在我正在测试的方法中,我有这样的代码:
public int[] MethodToTest(IQueryable<Poco> pocos, MockableDependency dependency)
{
var mostRecentUpdate = (from poco in pocos
select poco.Date_Last_Updated).Max();
var recentPocos = pocos.Where(x => x.Date_Last_Updated.CompareTo(mostRecentUpdate) >= 0);
///...snip...
result[0] = SomePrivateCalculation(recentPocos.Count);
result[1] = dependency.DoADifferentCalculation(recentPocos);
}
我已经在嘲笑MockableDependency
了,所以我实际上并不需要担心Poco
中pocos
的内容。但是,我希望能够控制recentPocos.Count
的价值,并且我希望能够知道无论在pocos
上运行多少查询,它都会返回相同的值在访问.Count
之前。
答案 0 :(得分:1)
MattiasG暗示解决方案。您应该提供一个IQuerable pocos,它始终会生成一个具有已知结果的查询,为您提供您期望的.Count。
所以代码中没有显示的是正确完成的;传递pocos的方法也应该被模拟,以提供可以进行适当断言的数据。
很难找到良好的测试平衡。这真的是一种艺术形式。但是如果你使用moq,你应该专注于高阶“工作单位”,而不是单个方法内部发生的事情。
换句话说。假设你设法让Count始终返回5.然后你有一个测试检查你的依赖方法中Count是否为5。它是。你做了什么?好吧,你可以声明Count将返回一个int(我们知道这已经有效了),但你还没有真正测试过你的应用程序代码。
但要回答你的实际问题: - 您必须创建一个新接口IMyOwnCustomMockableQuery&lt;&gt;,使用一些转换器或包装器类到IQuearble&lt;&gt;然后为你的IMyOwnCustomMockableQuery&lt;&gt;创建一个新的linq实现将你不想嘲笑的所有电话转发给IQuearble&lt;&gt;上的表决。
当然这很复杂,需要自己的测试。 =)对于测试不测试应用程序的测试的模型,似乎有很多工作要做。我不推荐这种方法。