Sunday, November 29, 2009

Stubs vs Mocks with Rhino Mocks

Recently I was asked: "What is the difference between Stubs and Mocks?" Martin Fowler has written a good article about that topic "Mocks Aren't Stubs". Also in the Rhino Mocks Wiki there is is comprehensive explanation.

Besides the theoretical aspect you have to decide whether to use

MockRepository.GenerateMock or

MockRepository.GenerateStub

when you use the "Arrange, Act, Assert" syntax of Rhino Mocks. To find out the detailed differences I wrote some tests, which are all green. I defined expected behaviour or stubbed behaviour with different syntax combinations. The behaviour is not called in any test. Only in the tests with the "ExpectedException" attribute RhinoMocks throws an exception:

[Test]
[(typeof(ExpectationViolationException))]
public void VerifyAllExpectationsWithExpectMethodOnMock()
{
   IList listMock = MockRepository.GenerateMock<IList>();
   listMock.Expect(x => x.Count).Return(10);

   listMock.VerifyAllExpectations();
}

[Test]
public void VerifyAllExpectationsWithExpectMethodOnStub()
{
   IList listStub = MockRepository.GenerateStub<IList>();
   listStub.Expect(x => x.Count).Return(10);

   listStub.VerifyAllExpectations();
}

[Test]
public void VerifyAllExpectationsWithStubMethodOnMock()
{
   IList listMock = MockRepository.GenerateMock<IList>();
   listMock.Stub(x => x.Count).Return(10);

   listMock.VerifyAllExpectations();
}

[Test]
public void VerifyAllExpectationsWithStubMethodOnStub()
{
   IList listStub = MockRepository.GenerateStub<IList>();
   listStub.Stub(x => x.Count).Return(10);

   listStub.VerifyAllExpectations();
}

[Test]
[ExpectedException(typeof(ExpectationViolationException))]
public void AssertWasCalledWithMock()
{
   IList listMock = MockRepository.GenerateMock<IList>();

   listMock.AssertWasCalled(x => { int temp = x.Count; });
}

[Test]
[ExpectedException(typeof(ExpectationViolationException))]
public void AssertWasCalledWithStub()
{
   IList listStub = MockRepository.GenerateStub<IList>();

   listStub.AssertWasCalled(x => { int temp = x.Count; });
}
The conclusion from these tests are: If you need a mocking behaviour in Rhino Mocks that verifies your code under test, you have to use one of these two combinations of methods:
  1. GenerateMock with Expect(...) and VerifyAllExpectations()
  2. GenerateMock/GenerateStub with AssertWasCalled(...)

No comments: