Moq设置:根据条件传递值或It.IsAny <T>()的能力

ato*_*oth 2 c# moq

[问题类似于:将It.IsAny <int>()和It.IsAny <int>()的值传递给方法设置有什么区别 - 需要进一步说明]

精简版

(以下更多定义)

我处在需要在工厂安装模拟的情况.根据价值,我想选择使用它还是It.IsAny<TTypeOfValue>().

这就是我(天真)想要做的事情:

moq.Setup(() => mockWebService.WebServiceMethod(
    webServiceMethodObject.Some ?? It.IsAny<string>(), // that fails
    ...,
    out webServiceMethodObject.That,
    ...)).Returns(webServiceMethodObject.ReturnEnum);
Run Code Online (Sandbox Code Playgroud)

我有这么大的参数列表(旧的遗留Web服务方法)和许多不同的值组合,我不想手工编写,也It.IsAny<T>()不想在任何地方使用,因为我想根据参数控制返回值.

一个可能的替代方案应该是版本,我可以将具体值与具体返回类型匹配,当没有具体值可以匹配时,它会回退到最广泛的版本(所有参数都替换为It.IsAny<T>().(简短示例:在登录测试中)我想测试一个登录方法的不同输入参数的不同返回值.在所有其他测试中,我只想返回LoginSuccess).

我怎样才能做到这一点?只有一些表达/反射魔法?


更长的解释

这就是我们典型的遗留Web服务的样子:

ReturnValueEnum WebServiceMethod(string some, int thing, ..., out int that, out byte[] those, ...) { ... }
Run Code Online (Sandbox Code Playgroud)

我们需要这么多的webservice方法调用,并且它们对参数非常臃肿,我们不得不将它们封装在对象中.例:

public class WebServiceMethodObject
{
    public string Some { get; set; }
    public int Thing { get; set; }
    ...
    public ReturnValue ReturnEnum { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

策略应该是:我们正在创建此对象的默认版本.在测试中,我们填写了需要匹配的值.我们希望将对象传递给要写入的方法,该方法相应地设置模拟:

如果设置了属性:使用该值

else:使用It.IsAny<T>()(参见上面的设置!).

Raw*_*ing 7

我会想到如果

webServiceMethodObject.Some ?? It.IsAny<string>()
Run Code Online (Sandbox Code Playgroud)

是你想要但不起作用的,简单的替代就是

It.Is<string>(v =>
    webServiceMethodObject.Some == null ||
    webServiceMethodObject.Some == v)
Run Code Online (Sandbox Code Playgroud)