Moq 验证方法不适用于 ToList
Moq Verify method not working with 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()
方法。为什么会这样?
简而言之,Moq 在参考基础上比较 List<T>
个实例。这两个 ToList
调用创建了两个单独的集合,因此它们的引用不同。
为了克服这个问题,您需要在 Verify
中使用 It.Is
problematicMock.Verify(
x => x.someMethod(
It.Is<List<string>>(input => AssertCollection(stringCollection.ToList(), input))),
Times.Once());
It.Is
收到 Func<List<string>, bool>
代表
input
是 someMethod
调用的参数
这是 AssertCollection
:
的简单实现
public static bool AssertCollection(List<string> expected, List<string> actual)
{
try
{
Assert.Equal(expected, actual);
}
catch
{
return false;
}
return true;
}
如果您将 stringCollection.ToList()
作为预期值传递,那么它将通过,但如果您通过
stringCollection.Reverse.ToList()
或 stringCollection.Skip(1).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()
方法。为什么会这样?
简而言之,Moq 在参考基础上比较 List<T>
个实例。这两个 ToList
调用创建了两个单独的集合,因此它们的引用不同。
为了克服这个问题,您需要在 Verify
It.Is
problematicMock.Verify(
x => x.someMethod(
It.Is<List<string>>(input => AssertCollection(stringCollection.ToList(), input))),
Times.Once());
It.Is
收到Func<List<string>, bool>
代表input
是someMethod
调用的参数
这是 AssertCollection
:
public static bool AssertCollection(List<string> expected, List<string> actual)
{
try
{
Assert.Equal(expected, actual);
}
catch
{
return false;
}
return true;
}
如果您将 stringCollection.ToList()
作为预期值传递,那么它将通过,但如果您通过
stringCollection.Reverse.ToList()
或 stringCollection.Skip(1).ToList()
那么它将失败。