一个返回自身的iquerable
本文关键字:iquerable 返回 一个 | 更新日期: 2023-09-27 17:54:01
我正在使用模拟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
,所以我实际上不需要担心pocos
中的Poco
是什么。但是,我希望能够控制recentPocos.Count
的值是什么,并且我希望能够知道,在访问.Count
之前,无论在pocos
上运行多少查询,它都会返回相同的值。
MattiasG暗示了解决方案。您应该提供一个可查询的pocos,它将始终生成一个带有已知结果的查询,并给出您期望的。count。
所以代码中没有显示的是正确的;传递pocos的方法也应该被模拟,以提供可以对其进行正确断言的数据。
很难找到一个好的测试平衡。这真的是一种艺术形式。但是如果你正在使用moq,你应该关注高阶的"工作单元",而不是单个方法内部发生的事情。
换句话说。假设你设法让Count总是返回5。然后你有一个测试在依赖方法中检查Count是否为5。它是。你完成了什么?好吧,你可以断言Count将返回一个int(我们知道这已经工作了),但是你还没有真正测试你的应用程序代码。
但要回答你的实际问题:-你必须做一个新的接口IMyOwnCustomMockableQuery<>,与一些转换器或包装类IQuearble<>,然后一个新的linq实现为你的IMyOwnCustomMockableQuery<>,转发所有调用你不想模拟的扩展IQuearble<>。
当然,这将是相当复杂的,需要自己的测试。=)似乎要做很多工作来测试你的模型,而不是测试你的应用程序。我不推荐这种方法。