MOQ'ing方法调用序列

时间:2014-06-06 14:40:11

标签: c# unit-testing moq

我正在嘲笑我们用于某些企业库调用的包装器。一切都在世界上很好,我的测试通过,实际的代码工作!

然而,我随后扩展了功能,并验证了所有测试仍然通过。宾果 - 他们做到了。然而,他们没有在现实世界,因为有一个期望

InitialiseDBCommand(string, commandtype)

将在

之前调用
AddCmdParameter(string, dbtype, object)

所以,就像一个好孩子一样,我要做的第一件事就是编写一个展示此行为的测试,并期望抛出异常。

我需要的是装配AddCmmParater以引发异常如果没有使用任何字符串调用InitialDBCommand。

我想我可以通过回调来做到这一点,但感觉就像moq'ing方法调用序列(不是方法返回序列)应该在那里。

这样的东西
iDataAccessHelper.Setup(s=>s.AddCmdOutputParameter(It.IsAny<string>(), 
                  It.IsAny<DbType>(), 
                  It.IsAny<int>()))
              .When(w=>w.InitialiseDBCommand(etc etc)
              .Throws<NullReferenceException>()

任何指针?

2 个答案:

答案 0 :(得分:3)

好吧,如果您只是想测试是否以正确的顺序调用了2个方法,一种方法是添加一个计数器,每次调用其中一个方法时递增,然后检查它是否是正确的数字。 Here是描述它的一个答案。 以下是我为您的场景编写的方法:

[Test]
public void TestingCallOrder() {
    int counter = 0;
    var mockDataAccessStuff = new Mock<IDataAccessStuff>();
    mockDataAccessStuff.Setup(x => x.AddCmdParameter(It.IsAny<string>())).Callback(() => {
        Assert.AreEqual(counter, 0);
        counter++;
    });

    mockDataAccessStuff.Setup(x => x.InitialiseDbCommand(It.IsAny<string>())).Callback(() => {
        Assert.AreEqual(counter, 1);
        counter++;
    });

    // more of the same
    var myClass = new ClassThatImTesting(mockDataAccessStuff.Object);
    myClass.DoWork();

    // make sure both methods are called at least once ...
    mockDataAccessStuff.Verify(x => x.AddCmdParameter(It.IsAny<string>()), Times.Once());
    mockDataAccessStuff.Verify(x => x.InitialiseDbCommand(It.IsAny<string>()), Times.Once());
}

我认为编写测试的方式非常简洁易读。

答案 1 :(得分:3)

有一个库扩展了Moq以添加名为Moq Sequences的此功能。从他们的例子看起来像

using (Sequence.Create())
{
    mock.Setup(_ => _.Method1()).InSequence();
    mock.Setup(_ => _.Method2()).InSequence(Times.AtMostOnce());
    ...
    // Logic that triggers the above method calls should be done here.
    ...

}";

断言在Method2

之前调用Method1