How do I mock a method call inside the method I want to test using NUnit?

9.9k views Asked by At

I'm trying to unit test a method and mock the method call inside it:

class LoginViewModel
{
public bool LogUserIn(string hashedPassword)
    {
        //Code
        if (loginSuccessful)
        {
            GoToMainMenu(); // I WANT TO MOCK THIS CALL.
            return true;
        }
         return false;
    }
}

so I want to mock the GoToMainMenu() function call, as this is only for navigation and I get an exception thrown here when I try to run my test.

I've tried using NUnit.Mocks:

    [Test]
    public void Log_User_In_Will_Return_True()
    {
        DynamicMock mockView = new DynamicMock(typeof(LoginViewModel));
        mockView.ExpectAndReturn("GoToMainMenu", null);
        LoginViewModel loginVM = (LoginViewModel)mockView.MockInstance; //ArgumentException
        Assert.AreEqual(true, loginVM.LogUserIn("aHashedPassword"));
    }

But this gives me an ArgumentException.

I've spent a lot of time trying different ways to make this work and have also tried Rhino Mocks but couldn't get my head around how to mock this call. Can anyone help with this? I haven't tried Moq but suspected it to be similar to Rhino Mocks.

1

There are 1 answers

0
k.m On BEST ANSWER

In your current setup this what you're trying to do is impossible. Few things to fix:

  • start using stable version of Rhino (like 3.6). Better yet, upgrade to Moq which is a newer framework
  • make GoToMainMenu method virtual (and at least protected)

Your test then (Rhino 3.6) should look like this:

var mock = MockRepository.GenerateMock<LoginViewModel>();
Assert.AreEqual(true, mock.LogUserIn("aHashedPassword"));

Few things to note here. Any non-virtual method called will use your original implementation (like LogUserIn). Every virtual method on the other hand will be replaced by RhinoMocks with default (do nothing) implementation, which should be enough to make test pass. The same test in Moq:

var mock = new Mock<LoginViewModel>();
Assert.AreEqual(true, mock.Object.LogUserIn("aHashedPassword"));

The way it works like this (need to have virtual methods) is because when creating a mock, both Rhino and Moq will generate in memory assembly and create new type there, deriving from your type (in your case, LoginViewModel). Derived type (mock) can then replace any method of original type given it's virtual (standard C# mechanism) or type is interface - then the mock simply implements the interface.