如何简化设置 Mocks 的 It.IsAny<T>() 参数

How to simplify the It.IsAny<T>() parameters for setting up Mocks

在我们的单元测试中,我们经常使用 Mock.Setup。这会导致如下语句:

_mockedModel.Setup(x => x.Method1(It.IsAny<string>(), It.IsAny<object>(),It.IsAny<string>())).Returns(1);
_mockedModel.Setup(x => x.Method2(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<object>())).Returns(1);
_mockedModel.Setup(x => x.Method3(It.IsAny<object>(), It.IsAny<object>(), It.IsAny<string>())).Returns(1);
_mockedModel.Setup(x => x.Method4(It.IsAny<object>(), It.IsAny<object>(), It.IsAny<object>())).Returns(1);

这很冗长,我想简化 It.IsAny<T>() 参数。

我们已尝试执行以下操作:

Func<string> s = It.IsAny<string>;
Func<object> o = It.IsAny<object>;
_mockedModel.Setup(x => x.Method1(s(), o(), o())).Returns(1);
_mockedModel.Setup(x => x.Method2(s(), o(), o())).Returns(1);
_mockedModel.Setup(x => x.Method3(o(), o(), s())).Returns(1);
_mockedModel.Setup(x => x.Method4(o(), o(), o())).Returns(1);

但是,虽然这不会给出任何错误,但它不会设置 Mock。例如。方法 1 到 4 return 0 而不是 1.

But, although this does not give any errors, it does not Setup the Mock. E.g. Methods 1 to 4 return 0 and not 1.

这是因为 Moq Setup 明确地在表达式中寻找 It.IsAny<T>() 静态方法调用,以便正确配置设置。这是设计使然。

通过在尝试简化表达式时更改为函数,您强制表达式调用方法调用,returns 泛型类型参数的默认值。

所以你的表达效果就变成了

_mockedModel.Setup(x => x.Method1(null, null, null)).Returns(1);
//...

@Nkosi 的回答帮助我想出了一个解决方案。解决方案是将 It.IsAny() 调用放在 属性(或方法)中:

private static string Str => It.IsAny<string>();
private static object Obj => It.IsAny<object>();

这使得代码可以这样写:

_mockedModel.Setup(x => x.Method1(Str, Obj, Obj)).Returns(1);
_mockedModel.Setup(x => x.Method2(Str, Obj, Obj)).Returns(1);
_mockedModel.Setup(x => x.Method3(Obj, Obj, Str)).Returns(1);
_mockedModel.Setup(x => x.Method4(Obj, Obj, Obj)).Returns(1);