起订量验证方法不适用于 ToList
我对 C# 单元测试和学习使用 Moq 相当陌生。下面是我的 Moq Verify()
方法问题的示例。
[Theory]
[AutoData]
public async Task WhenSomething_ThenSomething(IEnumerable<string> stringCollection)
{
//Arange
//Mock of the method used in Handle() that returns stringCollection.
someMock.Setup(x => x.MethodReturningStringCollectionForHandler()).ReturnsAsync(stringCollection);
var someList = stringCollection.ToList();
//Act
await handler.Handle(new SomeRequest(someId));
//Assert
//I want to verify if someMethod() inside handler was called once but with appropriate stringCollection
problematicMock.Verify(x => x.someMethod(someList), Times.Once());
}
上面的场景有效,但是当我删除 someList
变量并直接在 Verify()
中使用 ToList()
时,如下所示:
problematicMock.Verify(x => x.someMethod(stringCollection.ToList()), Times.Once());
然后我得到以下异常:
Message:
Moq.MockException :
Expected invocation on the mock once, but was 0 times: x => x.someMethod(["83436e1f-bd2f-44d3-9f8c-ba6afbf73e95", "16593c11-0959-4ebe-aafd-d5fbe0cfbd17", "633e6557-bed0-4ff0-b550-8790fab9e629"])
可以想象,这是一个很大的问题,如果 someMethod()
接受许多集合类型参数怎么办?对于这个特定的示例,我必须创建许多变量来传递给 Verify()
方法。为什么会这样?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
简而言之,Moq 在参考基础上比较
List
实例。两个ToList
调用创建两个单独的集合,因此它们的引用不同。为了克服这个问题,您需要在
Verify
中使用It.Is
Func
委托;, bool>
input
是someMethod
调用的参数这是
AssertCollection
的简单实现:如果您通过
stringCollection.ToList()
作为预期值那么它会通过,但是如果你通过stringCollection.Reverse.ToList()
或stringCollection.Skip(1).ToList()
那么它将失败。In short Moq compares
List<T>
instances on reference basis. The twoToList
calls create two separate collections therefor their references are different.In order to overcome of this you need to use
It.Is
inside yourVerify
It.Is
receives aFunc<List<string>, bool>
delegateinput
is the argument of thesomeMethod
callHere is a naive implementation of the
AssertCollection
:If you pass
stringCollection.ToList()
as an expected value then it will pass, but if you passstringCollection.Reverse.ToList()
orstringCollection.Skip(1).ToList()
then it will fail.