用MOQ模拟方法输出不同的每个调用参数

时间:2016-02-10 17:32:09

标签: c# unit-testing testing moq out

MOQ是否有办法对方法进行顺序调用,返回不同的out参数? 有关获取方法的快速示例:

public void OutputANumber(out int number)

输出1,然后输出2(忽略它可以返回int的事实,它只是一个例子而不是实际代码)。

int number = 1;
mock.Setup(n => n.OutputANumber(out number));
number = 2;
mock.Setup(n => n.OutputANumber(out number));

没有工作,因为第二个设置会覆盖第一个,同样SetupSequence只允许顺序返回。

2 个答案:

答案 0 :(得分:0)

一种解决方案是使用回调将模型传递给运行新设置的方法,如此

int number = 1;
mock.Setup(n => n.OutputANumber(out number)).Callback(() => ChangeOut(mock));

void ChangeOut(Mock<type> mock)
{
    int number = 2;
    mock.Setup(n => n.OutputANumber(out number));
}

或者您可以创建一个跟踪调用次数的虚拟对象,并根据需要输出新值。

答案 1 :(得分:0)

如果你只需要两个顺序调用,那么LukeW的解决方案可以解决。但是如果序列越长,它就会变得太复杂。您可以使用Typemock Isolator更轻松地解决问题。看一下下面的例子:

public class ClassUnderTest
{
    public void OutputANumber(out int number)
    {
        number = 3;
    }
}

[TestMethod, Isolated]
public void TestOutSequence()
{
    //Arrange
    var n = new ClassUnderTest();

    int number = 1;
    Isolate.WhenCalled(() => n.OutputANumber(out number)).IgnoreCall();
    number = 2;
    Isolate.WhenCalled(() => n.OutputANumber(out number)).IgnoreCall();
    Isolate.WhenCalled(() => n.OutputANumber(out number)).CallOriginal();

    //Act
    var res1 = 0;
    var res2 = 0;
    var resOriginal = 0;
    var resDefault = 0;
    n.OutputANumber(out res1);
    n.OutputANumber(out res2);
    n.OutputANumber(out resOriginal);
    n.OutputANumber(out resDefault);

    //Assert
    Assert.AreEqual(1, res1);
    Assert.AreEqual(2, res2);
    Assert.AreEqual(3, resOriginal);
    Assert.AreEqual(3, resDefault);
}

无需创建虚拟对象或其他方法。通过串行定义param并使用Isolate.WhenCalled(),您可以设置任何out参数序列:

int number = 1;
Isolate.WhenCalled(() => n.OutputANumber(out number)).IgnoreCall();

最后一次调用Isolate.WhenCalled()定义了从那一刻开始的方法的默认行为。因此,在示例中,我返回了在伪调用后调用的原始实现:

Isolate.WhenCalled(() => n.OutputANumber(out number)).CallOriginal();