C# 多个 Moq It.Is<string>() 匹配参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9122070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 06:04:23  来源:igfitidea点击:

Multiple Moq It.Is<string>() Matching Arguments

c#unit-testingmockingmoq

提问by Nicholas Murray

With Moq, is it valid to have more than one Matching Argument?

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

It.Is<string>() 

In this example I want the mockMembershipService to return a different ProviderUserKey depending on the User supplied.

在此示例中,我希望 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");

The SetUp defaults to the second statement rather than evaluating each on its own merits.

SetUp 默认为第二个语句,而不是根据其自身的优点评估每个语句。

采纳答案by Ufuk Hac?o?ullar?

Isn't it confusing? You are trying to mock GetUser method but you set the Returns for that function's return value's property. You also want to state return type's property based on mocked method.

是不是很混乱?您正在尝试模拟 GetUser 方法,但您为该函数的返回值属性设置了 Returns。您还想根据模拟方法声明返回类型的属性。

Here's a way a more clear way:

这是一种更清晰的方法:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>())
                     .Returns<string>(GetMembershipUser);

Here's a method to create the membership mock:

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

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

Then you write a method for setting that property:

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

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

回答by Bartosz

Succesive Setup calls nullify previous setups.

连续设置调用使以前的设置无效。

You could use your argument in your return callback:

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

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";
});

If it's important to you to assert the argument passed, you also need It.Is<string>(...)instead of It.IsAny<string>(...).

如果断言传递的参数对您很重要,您还需要It.Is<string>(...)代替It.IsAny<string>(...).

回答by cadrell0

If you want to restrict input to just "Joe" and "Tracy", you can specify multiple conditions in It.Is<T>(). Something like

如果您只想将输入限制为“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 */);

回答by Jaider

Please check Introduction to Moq > Matching Arguments documentation:

请查看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");