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

In dependency of some condition, count of calls of Method2 should not be more than 3. Test is checking, does that logic work as expected for a concrete query.

The issue is: nobody can exactly know which values should be returned. Also, it may be a very large set. I guess, It.IsAny<>() would be in a right place here, but it doesn't work with out parameters.

Is there something for such cases?

anatol
  • 1,680
  • 2
  • 24
  • 47

2 Answers2

1

Like I commented on your own answer, don't use It.* matchers in places where Moq won't perform any matching; because if you do, people reading your code might easily be misled into expecting that Moq will perform some kind of argument matching (which is not the case, matchers only apply to input parameters).

Using It.Ref<T>.IsAny still works because it is nothing more than a static field of type T. But you could just as well use any other field or variable of an appropriate type. Doing just that — using another variable — would be my suggestion to prevent the problem mentioned above (misleading code).

// 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));
//                                                    ^^^^^  ^^^^^^
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
0

I've solved it by inlining ref-matches.

myClassMock
.Verify(v => 
        v.Method2(It.IsAny<string>(), out It.Ref<byte>.IsAny, out It.Ref<string>.IsAny,),
                  Times.AtMost(3));   
anatol
  • 1,680
  • 2
  • 24
  • 47
  • Like I mentioned [there](https://stackoverflow.com/questions/1068095/assigning-out-ref-parameters-in-moq/47723362?noredirect=1#comment90914090_47723362), using an `It` matcher that way doesn't really make sense, because Moq only performs argument matching for input parameters. Your use of a matcher for an `out` parameter suggests that you expect Moq to perform matching there, which is misleading. I suggest you use dummy variables instead of Moq's matchers for clarity. For example, declare a dummy variable `byte _` and pass it as `out _`; same for the string parameter. – stakx - no longer contributing Aug 23 '18 at 11:28