代码之家  ›  专栏  ›  技术社区  ›  anatol

如何在模拟类方法的Setup`/`Verify`中使用'out'参数?

  •  0
  • anatol  · 技术社区  · 8 年前
    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<>() 会在一个合适的地方,但不适合 out 参数。

    这类案件有什么处理办法吗?

    2 回复  |  直到 8 年前
        1
  •  1
  •   stakx - no longer contributing Saravana Kumar    8 年前

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

    使用 It.Ref<T>.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
  •  0
  •   anatol    8 年前

    我通过内联解决了这个问题 ref -火柴。

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