Multiple Moq It.Is <string>()匹配参数

Nic*_*ray 67 c# unit-testing moq mocking

使用Moq,拥有多个匹配参数是否有效?

It.Is<string>() 
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我希望mockMembershipService根据用户提供的内容返回不同的ProviderUserKey.

mockMembershipService.Setup(
    x => x.GetUser(
      It.Is<string>(
        s => s.Contains("Joe")))
   .ProviderUserKey)
.Returns("1234abcd");


mockMembershipService.Setup(
  x => x.GetUser(
    It.Is<string>(
      s => s.Contains("Tracy")))
  .ProviderUserKey)
.Returns("5678efgh");
Run Code Online (Sandbox Code Playgroud)

SetUp默认为第二个语句,而不是根据它自己的优点来评估每个语句.

Ufu*_*arı 45

这不是很困惑吗?您正在尝试模拟GetUser方法,但您为该函数的返回值的属性设置了Returns.您还希望根据模拟方法声明返回类型的属性.

这是一种更清晰的方式:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>())
                     .Returns<string>(GetMembershipUser);
Run Code Online (Sandbox Code Playgroud)

这是创建成员模拟的方法:

private MembershipUser GetMembershipUser(string s)
{
    Mock<MembershipUser> user =new Mock<MembershipUser>();
    user.Setup(item => item.ProviderUserKey).Returns(GetProperty(s));
    return user.Object;
}
Run Code Online (Sandbox Code Playgroud)

然后你编写一个设置该属性的方法:

private string GetProperty(string s)
{
    if(s.Contains("Joe"))
        return "1234abcd";
    else if(s.Contains("Tracy"))
        return "5678efgh";
}
Run Code Online (Sandbox Code Playgroud)


cad*_*ll0 27

如果要将输入限制为"Joe"和"Tracy",则可以指定多个条件It.Is<T>().就像是

mockMembershipService.Setup(x => x.GetUser(It.Is<String>(s => s.Contains("Joe") 
                                                         || s.Contains("Tracy")))
    .Returns<string>(/* Either Bartosz's or Ufuk's answer */);
Run Code Online (Sandbox Code Playgroud)


Bar*_*osz 15

成功设置调用使先前的设置无效.

您可以在返回回调中使用您的参数:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>()).ProviderUserKey).Returns<string>(s =>
{
    if(s.Contains("Joe"))
        return "1234abcd";
    else if(s.Contains("Tracy"))
        return "5678efgh";
});
Run Code Online (Sandbox Code Playgroud)

如果断言传递的参数很重要,那么你也需要It.Is<string>(...)代替It.IsAny<string>(...).


Jai*_*der 9

请查看“Moq 简介”>“匹配参数”文档:

// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); 


// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); 


// matching regex
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");
Run Code Online (Sandbox Code Playgroud)

  • 现在有了更多的单元测试经验,我不推荐这种方法。我们应该避免将逻辑放在单元测试中。另一种选择是创建单独的单元测试:一个用于 **Joe**,另一个用于 **Tracy** (3认同)