Home > Software design >  migrate unit tests written with NMock2 to Moq
migrate unit tests written with NMock2 to Moq

Time:07-07

I am asked to upgrade a very old codebase to .net 6 and after upgrading the unit tests no longer pass because the mock library NMock2 doesn't support .net 6. I try to replace the old mock library with Moq but encountered new problems. Since I am no expert in either of the libraries, can someone please help me with the upgrading?

tl;dr What are the equivalents to Expect.Exactly(3).On(aHandlerMock).Method("APublicMethod").WithAnyArguments() and Expect.Exactly(2).On(aHandlerMock).GetProperty("AOnlyGetterAvailableProperty").Will(Return.Value(false))

Details of the problem:

Test class with NMock2 involved looks like this:

[SetUp]
public void SetUp()
{
    this.mockery = new Mockery();
    this.messageDelegatorMock = this.mockery.NewMock<IDispatcher>();
    this.xHandlerFactoryMock = this.mockery.NewMock<IXHandlerFactory>();
    this.xHandlerMock = this.mockery.NewMock<IXHandler>();
    this.incomingXDelegate = new IncomingXDelegate(this.messageDelegatorMock) 
    {
        XHandlerFactory = this.xHandlerFactoryMock
    };
}

[Test]
public void TestHandleXSimple()
{
    TestX testX = new TestX(new Collection<string>());

    CY y1 = new CY("1", 0, false);
    CY y2 = new CY("1", 1, false);
    CY y3 = new CY("1", 2, true);

    Expect.Once.On(this.xHandlerFactoryMock)
        .Method("createXHandler")
        .With(typeof(TestX), "1")
        .Will(Return.Value(this.xHandlerMock));

    Expect.Exactly(3).On(this.xHandlerMock)
        .Method("addMessage")
        .WithAnyArguments();
     
    Expect.Exactly(2).On(this.xHandlerMock)
        .GetProperty("IsComplete")
        .Will(Return.Value(false));
    
    Expect.Once.On(this.xHandlerMock)
        .GetProperty("IsComplete")
        .Will(Return.Value(true));
    
    Expect.Once.On(this.XHandlerMock)
        .GetProperty("Message")
        .Will(Return.Value(testX));

    Expect.Once.On(this.messageDelegatorMock).Method("Dispatch");

    incomingXDelegate.OnX(testX, y1);

    incomingXDelegate.OnX(testX, y2);

    incomingXDelegate.OnX(testX, y3);

    mockery.VerifyAllExpectationsHaveBeenMet();
}

addMessage(object message, IMh info) is declared in IXHandler and in the test fixture, class CY implements IMh.

My question would be: how can I make use of Moq to mimic the behaviors of NMock2 in the example? Thank you very much for your generous help!

CodePudding user response:

I don't have any experience with NMock2, but that code seems fairly explicit in what it is expecting.

Given that, and assuming that the class being tested looks like the following:

public interface IXHandlerFactory
{
  void APublicMethod(int argOne, int argTwo);
  bool AOnlyGetterAvailableProperty { get; }
}

Expect.Exactly(3).On(aHandlerMock).Method("APublicMethod").WithAnyArguments()

Would look like this:

//Create the mock and call the method as an example
var mock = new Mock<IXHandlerFactory>();
mock.APublicMethod(1, 2);

//Verify the method was called the expected number of times with any value
//for the arguments
mock.Verify(x => x.APublicMethod(It.IsAny<int>(), It.IsAny<int>()), Times.Exactly(3));

The Times class in Moq has a bunch of useful method for specifying how often (if at all) the expected method is is invoked. If the expectation does not match, an exception will be thrown which typically fails a test in the frameworks I've worked with in the past.

The It class likewise has a bunch of methods on it such as Any (i.e. I don't care what the value is) or if you want to be more specific, there is an Is where you can plug-in a custom comparison.

Expect.Exactly(2).On(aHandlerMock).GetProperty("AOnlyGetterAvailableProperty").Will(Return.Value(false))

would look like this:

//Create the mock as before
var mock = new Mock<IXHandlerFactory>();

//Any calls to AOnlyGetterAvailableProperty will return false
mock.Setup(x => x.AOnlyGetterAvailableProperty).Returns(false);

//Run the test

//Assert the expectation
mock.Verify(x => x.AOnlyGetterAvailableProperty, Times.Exactly(2));
  • Related