3

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?

Liath
  • 9,913
  • 9
  • 51
  • 81
Jon H
  • 1,061
  • 4
  • 13
  • 32
  • What are you actually testing ? Which method ? `AddCmdParameter` ? You should write this scenario as a unit test not a complex mock scenario. – Dimitar Dimitrov Jun 06 '14 at 14:45
  • 2
    @DimitarDimitrov simply put I believe the OP wants a test which proves that InitialiseDBCommand is called before AddCmdParameter – Liath Jun 06 '14 at 14:46
  • 1
    I am testing a method called 'WriteBlob' that uses a data access layer. The data access layer contains these 2 calls, which it seems have an order dependency. I can see what our getting at - the test for this needs to be closer to the data access layer code itself. – Jon H Jun 06 '14 at 14:47
  • This has been asked [here](http://stackoverflow.com/questions/10602264/using-moq-to-verify-calls-are-made-in-the-correct-order) and [here](http://stackoverflow.com/questions/1765738/how-to-test-method-call-order-with-moq) – Patrick Quirk Jun 06 '14 at 14:56
  • They seem to relate more to multiple calls to the same method, each returning a differing value. Support which is now within Moq. – Jon H Jun 06 '14 at 15:00

2 Answers2

3

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.

Community
  • 1
  • 1
Dimitar Dimitrov
  • 14,868
  • 8
  • 51
  • 79
3

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

Sign
  • 1,919
  • 18
  • 33
  • This sounds like what I was looking for.. why don't they incorporate it into Moq actual! – Jon H Jun 06 '14 at 15:22