I’ve found a strange issue using Moq doing some TDD, take a look at this snippet:

[TestMethod]
public void SampleTest()
{
    var mock = new Mock<IMessageBroker>();
    mock.Setup( b => b.Broadcast( It.IsAny<EventMessage>() ) );
    mock.Setup( b => b.Broadcast( It.Is<EventMessage>( m => m.EventID.StartsWith( "id/" ) ) ) )
        .Verifiable();
 
    var sut = new SomeComponent( mock.Obect );
    sut.DoSomethingThatFiresTwoMessages();
 
    mock.VerifyAll();
}

Nothing special, we have a message broker, mocked, and a component that depends on the broker, one method of the component can fire 2 messages, we are currently interested in verifying just the last message.

Disclaimer: This is not the real scenario but a simplification for this post, just to identify the issue.

Even if the tested component behaves correctly the test fails, in this special case with a null reference exception…uhm

The problem, once identified, is fairly simple the Moq engine always calls the second setup never the first and in my case the first message contains a null EventId; this explains the null reference exception but not the weird behavior.

As far as I have understood Moq utilizes the Lambda Expressions passed the the setup method to determine the shape of the call and in my scenario both call have exactly the same shape and the second one overrides the first one setup producing the weird behavior.

Workarounds

I’ve experimented a couple of workarounds to solve the problem, the first one is to delay the setup chain:

[TestMethod]
public void SampleTest()
{
    var mock = new Mock<IMessageBroker>();
    mock.Setup( b => b.Broadcast( It.IsAny<EventMessage>() ) )
        .Callback( () => 
        {
            mock.Setup( b => b.Broadcast( It.Is<EventMessage>( m => m.EventID.StartsWith( "id/" ) ) ) )
                .Verifiable();
        } );
 
    var sut = new SomeComponent( mock.Obect );
    sut.DoSomethingThatFiresTwoMessages();
 
    mock.VerifyAll();
}

Note the highlighted Callback method, we simply delay the second setup when the first call is done, but this is not always possible or can take to really ugly and unreadable code due to lots of nested setup calls.

Another approach, that perfectly works in my scenario, is to drop the verify support of Moq and take care by yourself of the verification of what has happened:

[TestMethod]
public void SampleTest()
{
    var history = new List<EventMessage>();
 
    var mock = new Mock<IMessageBroker>();
    mock.Setup( b => b.Broadcast( It.IsAny<EventMessage>() ) )
        .Callback<EventMessage>( msg => history.Add( msg ) );
 
    var sut = new SomeComponent( mock.Obect );
    sut.DoSomethingThatFiresTwoMessages();
 
    //your assert on history here:
    history.Should().Have.Count.EqualsTo( 2 );
    //more assert if required.
}

We simply use the callback to record in the history list all the broadcasted messages and after that we asset on the history list.

.m