【问题标题】:How to work with `out` parameters in `Setup`/`Verify` for mocked class methods?如何在“Setup”/“Verify”中使用“out”参数来模拟类方法?
【发布时间】:2018-08-23 10:37:36
【问题描述】:
public class MyClass
{
   public virtual void Method1(string par1, int par2)
   {
      // ...

      var result = new Dictionary<byte, string>();
      for(var i = 0; i < 100; i++)
      {
         if(someCondition) break;
         Method2(par1, out byte res1, out string res2);
         result[res1] = res2;
      }

      // ...
   }

   public virtual void Method2(string par1, out byte res1, out string res2)
   {
      // ...

      res1 = 1;
      res2 = "res2";

      // ...
   }
}

    // test class
public class MyClassTests
{
   [Fact]
   public void TestMethod()
   {
      string par1 = "value";
      int par2 = 2;
      var myClassMock = new Mock<MyClass>() { CallBase = true };

      myClassMock.Verify(v => v.Method1(par1, par2), Times.Once);
      myClassMock.Verify(v => v.Method2(It.IsAny<string>(), out ?, out ?), Times.AtMost(3));
   }
}

根据某些条件,Method2 的调用次数不应超过 3。测试正在检查,该逻辑是否按预期对具体查询工作。

问题是:没有人能确切知道应该返回哪些值。此外,它可能是一个非常大的集合。我想,It.IsAny&lt;&gt;() 会在正确的位置,但它不适用于out 参数。

这种情况有什么办法吗?

【问题讨论】:

    标签: c# unit-testing moq out


    【解决方案1】:

    就像我在 your own answer 上的 commented 一样,不要在 Moq 不会执行任何匹配的地方使用 It.* 匹配器;因为如果你这样做了,阅读你的代码的人可能很容易被误导以为 Moq 会执行某种参数匹配(事实并非如此,匹配器仅适用于输入参数)。

    使用It.Ref&lt;T&gt;.IsAny 仍然有效,因为它只不过是T 类型的静态字段。但是您也可以使用适当类型的任何其他字段或变量。这样做——使用另一个变量——将是我防止上述问题(误导性代码)的建议。

    // declare some dummy variables; the names don't matter.
    byte _;
    string __;
    
    // then use & forget about them.
    myClassMock.Verify(v => v.Method2(It.IsAny<string>(), out _, out __), Times.AtMost(3));
    //                                                    ^^^^^  ^^^^^^
    

    【讨论】:

      【解决方案2】:

      我已经通过内联ref-matches 解决了这个问题。

      myClassMock
      .Verify(v => 
              v.Method2(It.IsAny<string>(), out It.Ref<byte>.IsAny, out It.Ref<string>.IsAny,),
                        Times.AtMost(3));   
      

      【讨论】:

      • 就像我提到的there,以这种方式使用It 匹配器并没有真正意义,因为Moq 只对输入参数执行参数匹配。您对 out 参数使用匹配器表明您希望 Moq 在那里执行匹配,这是一种误导。为了清楚起见,我建议您使用虚拟变量而不是 Moq 的匹配器。例如,声明一个虚拟变量byte _,并将其传递为out _;字符串参数也一样。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      • 2015-05-12
      • 2019-11-12
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多