MOQ'ing method call sequence

戏子无情 提交于 2019-12-23 21:48:18

问题


I am mocking out a wrapper we use for some enterprise library calls. All was well in the world, my tests passed and the actual code worked!

However I then extended the functionality, and verified the tests all still passed. Bingo - they did. However they didn't in the real world because there is an expectation that

InitialiseDBCommand(string, commandtype)

will be called before

AddCmdParameter(string, dbtype, object)

So like a good boy, the first thing I want to do is write a test that exhibits this behavior and expects an exception to be thrown.

What I need is to rig up AddCmmParater to throw an exception IF InitialDBCommand has not been called with any string.

I figure I could do this with a call back, but it feels like moq'ing a method call sequence (not a method return sequence) ought to be there.

Something like

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

Any pointers?


回答1:


Well if you simply want to test if 2 methods are called in the correct order, one way to do it would be to add a counter that is incremented each time one of the methods is called and then check if it's the correct number. Here is one answer that describes it. Here is how I'd write it for your scenario:

[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());
}

I think that's a very clean and readable way to write the test.




回答2:


There is a library that extends Moq to add this functionality called Moq Sequences. Which from their examples looks like

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

}";

It asserts that Method1 is called before Method2



来源:https://stackoverflow.com/questions/24084511/moqing-method-call-sequence

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!