起订量返回本身
我使用设置测试一个IQueryable一个嘲笑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
s为在pocos
。但是,我希望能够控制recentPocos.Count
的值,并且我希望能够知道它将返回相同的值,无论在访问.Count
之前有多少查询在pocos
上运行。
MattiasG暗示了解决方案。你应该提供一个IQuerable pocos,它总是会生成一个查询,并带有一个已知的结果,给你你想要的.Count。
那么这里代码中没有显示的是正确的;传递pocos的方法也应该被嘲笑以提供可以在其上进行正确断言的数据。
很难找到一个良好的测试平衡。这真的是一种艺术形式。但是,如果你使用moq,你应该把重点放在高层次的'工作单元'上,而不是在单个方法中发生的事情。
换句话说。假设您设法让Count始终返回5.然后您有一个测试,检查您的依赖方法中Count是否为5。它是。你做了什么?那么,你可以断言Count会返回一个int(我们知道这已经在工作了),但是你根本没有真正测试过你的应用程序代码。
但是,为了回答您的实际问题: - 你将不得不作出一个新的接口IMyOwnCustomMockableQuery <>,一些转换器或包装类IQuearble <>,然后你IMyOwnCustomMockableQuery <>一个新的LINQ实现转发所有呼叫你不想嘲笑IQuearble <>上的exensions。
当然这会很复杂,需要自己的测试。 =)对于测试不测试应用程序的测试而言,似乎有很多工作可用于测试您的模型。我不会推荐这种方法。
它看起来像你不想嘲笑IQueryable,但LINQ查询。 – MatthiasG
这是什么意思? (我不知道LINQ是如何工作的) – Kevin
我不确定你如何用Moq模拟LINQ查询。我只是说,你想模拟函数'Where',这是LINQ提供的扩展方法,而不是'IQueryable'的一部分。 – MatthiasG