13

For a method like:

protected virtual bool DoSomething(string str) { }

I usually mock it through:

var mockModule = new Mock<MyClass> { CallBase = true };
mockModule.Protected().Setup<bool>("DoSomething", ItExpr.IsAny<string>()).Returns(true);

But for a method like:

protected virtual bool DoSomething(out string str) { }

How can I mock it?

David Pine
  • 23,787
  • 10
  • 79
  • 107
Mike
  • 395
  • 2
  • 4
  • 14
  • Possible duplicate of this: http://stackoverflow.com/questions/1068095/assigning-out-ref-parameters-in-moq – Rob May 27 '16 at 02:45
  • 2
    @Rob, you're claiming it is a duplicate of itself? That seems like a bug in SO to even allow that, lmafo! – David Pine May 27 '16 at 02:47
  • @DavidPine Sorry, wrong link! – Rob May 27 '16 at 02:47
  • Not certain if this will work but test with `mockModule.Protected().Setup("DoSomething", expectedValue)` where `expectedValue` is what you expect as outcome. Remove `Returns` – Claudio Redi May 27 '16 at 02:48
  • @ClaudioRedi Does not work :( – Mike May 27 '16 at 02:59
  • There are two ways in which you could avoid using `.Protected().`, and instead use the usual syntax `var yourStr = "Moq returns this"; mockModule.Setup(x => x.DoSomething(out yourStr)).Returns(true);`. The first option is to relax the access level of `DoSomething` from `protected` to `protected internal` (assuming you create `mockModule` in the same project where the class `MyClass` is defined). The second option is to write a test class that derives from `MyClass` and do the Setup of `x.DoSomething` inside the derived class. It is worth trying to avoid the need of string `"DoSomething"`. – Jeppe Stig Nielsen Jun 04 '16 at 09:06
  • What happens when you try @ClaudioRedi's approach ("not work" is not helpful)? – Jeppe Stig Nielsen Jun 04 '16 at 09:07

2 Answers2

14

It can be done since moq 4.8.0-rc1 (2017-12-08). You can use ItExpr.Ref<string>.IsAny for match any value for ref or out parameters. In your case:

mockModule.Protected().Setup<bool>("DoSomething", ItExpr.Ref<string>.IsAny).Returns(true);

Full example with mocking the out parameter:

[TestClass]
public class OutProtectedMockFixture
{
    delegate void DoSomethingCallback(out string str);

    [TestMethod]
    public void test()
    {
        // Arrange
        string str;
        var classUnderTest = new Mock<SomeClass>();
        classUnderTest.Protected().Setup<bool>("DoSomething", ItExpr.Ref<string>.IsAny)
            .Callback(new DoSomethingCallback((out string stri) =>
                {
                    stri = "test";
                })).Returns(true);

        // Act
        var res = classUnderTest.Object.foo(out str);

        // Assert
        Assert.AreEqual("test", str);
        Assert.IsTrue(res);
    }
}

public class SomeClass
{
    public bool foo(out string str)
    {
        return DoSomething(out str);
    }

    protected virtual bool DoSomething(out string str)
    {
        str = "boo";
        return false;
    }
}
itaiy
  • 1,152
  • 1
  • 13
  • 22
-4

It can be done by using Typemock Isolator, you can mock your non-public methods and change their out and ref parameters easily:

[TestMethod, Isolated]
public void test()
{
    // Arrange
    string str;
    SomeClass classUnderTest = new SomeClass();
    Isolate.NonPublic.WhenCalled(classUnderTest, "DoSomething").AssignRefOut("test").IgnoreCall();

    // Act
    classUnderTest.foo(out str);

    // Assert
    Assert.AreEqual("test", str);
}


public class SomeClass
{
    public void foo(out string str)
    {
        DoSomething(out str);
    }

    protected virtual bool DoSomething(out string str) 
    {
        str = "boo";
        return true;
    }
}

you can read more about it here.

Gregory Prescott
  • 574
  • 3
  • 10