When to Stub and When to Mock

I was actually going to talk about how to stub using TypeMock but then I found that a little explanation is required.

If you haven’t read Mocks Aren’t Stubs by Martin Fowler, you should read it now. In short The difference between Mocks and Stubs is in the verification.

Stubs are fake objects that are required for a test but the arguments passed and the number of times each method is called is not significant for the test.

Mocks are also fake objects that are required for a test, but the test verifies that the mocked methods where actually called and the arguments passed where expected.

An Example Please

Now for an example: Suppose we have a Logger class that has a Log() method that is being called throughout our code. We might be testing the logic of the method and logging is not being tested. In this case we can stub out the Logger, as we don’t care if it is called and how many times.

But, if we are testing the logging mechanism of the method, we can mock the Logger and Verify that Log was called once with the correct arguments.

Here are the examples:

public void TestMethod() { Logger.Log("Entered TestMethod"); // do logic... } [Test] public void StubLogging() { Mock logMock = MockManager.Mock(typeof(Logger)); logMock.ExpectAlways("Log"); ... TestMethod(); } [Test] public void MockLogging() { Mock logMock = MockManager.Mock(typeof(Logger)); logMock.Expect("Log").Args("Entered TestMethod"); ... TestMethod(); MockManager.Verify(); }

In the first test StubLogging we don’t care if and whether Logger.Log() was called. So we use ExpectAlways to always fake the Log() method. ExpectAlways will not fail if the method was never called or was called, it will simply fake the method when it is called.

In the second test MockLogging we do want to verify that Logger.Log() was called ONE time with “Entered TestMethod” as the argument. Here we use ExpectCall to fake the Log() method. ExpectCall will fail if Log() was not called. (And when the mock is Strict it will fail if too many Log() methods where called).
We also verify that the argument that was passed to Log() is “Entered TestMethod” by using Args(). If a different argument was called the test will fail.
We must finish the test with a call to MockManager.Verify() to insure that the test fails if the expected methods where not called.

Summary

So here is a summary of the different API’s to use for stubs and mocks

Stubs Mocks
MockAll – all instances Mock/MockObject – one instance
ExpectAlways – don’t care if the method was called ExpectCall – Count and Verify the number of calls.
Don’t check arguments Use Args() to verify arguments
No need to Verify Always Verify()
Not Strict Can be Strict

 

 

 

 

 

 

For advanced Stubs you can use DynamicReturnValues, ConditionalExpectations and VerifyMode but that is for my next blog.

Add Comment

Required fields are marked *. Your email address will not be published.