起订量返回本身

问题描述:

我使用设置测试一个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上运行。

+1

它看起来像你不想嘲笑IQueryable,但LINQ查询。 – MatthiasG

+0

这是什么意思? (我不知道LINQ是如何工作的) – Kevin

+1

我不确定你如何用Moq模拟LINQ查询。我只是说,你想模拟函数'Where',这是LINQ提供的扩展方法,而不是'IQueryable'的一部分。 – MatthiasG

MattiasG暗示了解决方案。你应该提供一个IQuerable pocos,它总是会生成一个查询,并带有一个已知的结果,给你你想要的.Count。

那么这里代码中没有显示的是正确的;传递pocos的方法也应该被嘲笑以提供可以在其上进行正确断言的数据。

很难找到一个良好的测试平衡。这真的是一种艺术形式。但是,如果你使用moq,你应该把重点放在高层次的'工作单元'上,而不是在单个方法中发生的事情。

换句话说。假设您设法让Count始终返回5.然后您有一个测试,检查您的依赖方法中Count是否为5。它是。你做了什么?那么,你可以断言Count会返回一个int(我们知道这已经在工作了),但是你根本没有真正测试过你的应用程序代码。

但是,为了回答您的实际问题: - 你将不得不作出一个新的接口IMyOwnCustomMockableQuery <>,一些转换器或包装类IQuearble <>,然后你IMyOwnCustomMockableQuery <>一个新的LINQ实现转发所有呼叫你不想嘲笑IQuearble <>上的exensions。

当然这会很复杂,需要自己的测试。 =)对于测试不测试应用程序的测试而言,似乎有很多工作可用于测试您的模型。我不会推荐这种方法。