Twitter LinkedIn Github

JetBrains

Having a chat with a colleague the other, brought up the issue of strict mocks. I commented that strict mocks should be used sparingly and only in certain circumstance, and this led to a series of discussions on why that is.

Strict and loose Mocks

Usually mocking frameworks provide two types of mocks: strict and loose. If you're using RhinoMocks, these are called StrictMock and DynamicMock. If you're using Moq, you set the behaviour (Loose = Dynamic = Default or Strict) in the mock creation.

 

RhinoMocks

RhinoMock has a static mock repository that you can use to create mocks, called MockRepository. This saves you on having to explicitly create a mock repository. Thus, instead of doing:

 

   1: MockRepository mocks = new MockRepository();
   2:  
   3: IDependency dependency = mocks.DynamicMock<IDependency>();

you could write this:

 

   1: IDependency dependency = MockRepository.GenerateMock<IDependency>();

Using the static repository, you cannot pick between dynamic and strict mocks. All mocks are dynamic. This somehow promotes the usage of dynamic mocks over strict ones.

 

Moq

With Moq, as with RhinoMocks, the default behaviour is of loose mocks. Thus, writing:

 

   1: var dependency = new Mock<IDependency>();

is equivalent to:

 

   1: var dependency = new Mock<IDependency>(MockBehavior.Loose);

which in turn is the same as:

 

   1: var dependency = new Mock<IDependency>(MockBehavior.Default);

If you want to use strict mocks:

 

   1: var dependency = new Mock<IDependency>(MockBehavior.Strict);

(Note that with Moq, to access the actual Mocked object, you need to access the .Object property. RhinoMocks doesn't require this because it uses extension methods).

 

Using Strict Mocks

So, now that we know how to create the two different types of mocks depending on the framework, let's take a look at a SUT and see where the problem with strict mocks lie. To make the post shorter, I'll use RhinoMocks, but you can accomplish the same with Moq.

Suppose we have the following class:

   1: public class ServiceClass 
   2:    {
   3:        private readonly IDependency _dependency;
   4:  
   5:        public ServiceClass(IDependency dependency)
   6:        {
   7:            _dependency = dependency;
   8:        }
   9:  
  10:        public void FirstMethod()
  11:        {
  12:            _dependency.FirstMethod();
  13:            Console.WriteLine("Called ServiceClass.FirstMethod");
  14:        }
  15:  
  16:        public void SecondMethod()
  17:        {
  18:            _dependency.SecondMethod();
  19:            Console.WriteLine("Called ServiceClass.SecondMethod");
  20:        }
  21:    }

 

and we want to test that when calling ServiceClass.FirstMethod, the corresponding call Dependency.FirstMethod is called, we could be tempted to do something like the following:

   1:        [Fact]
   2:        public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_Strict()
   3:        {
   4:            MockRepository mocks = new MockRepository();
   5:  
   6:            IDependency dependency = mocks.StrictMock<IDependency>();
   7:            
   8:            using (mocks.Record())
   9:            {
  10:                dependency.Expect(m => m.FirstMethod()); 
  11:            }
  12:  
  13:            using (mocks.Playback())
  14:            {
  15:                ServiceClass serviceClass = new ServiceClass(dependency);
  16:  

 17:                serviceClass.FirstMethod();
  18:            }
  19:  
  20:            // Note that in the Record/Replay, VerifyAll is implicitly called
  21:        }

 

We've verified that Dependency.FirstMethod is called, everything passes, all is fine.

 

Welcome to BrittleVille

Two days later we get a change of request, that requires us to adjust the code for ServiceClass.FirstMethod. In particular, we need to call Dependency.ThirdMethod:

   1: public void FirstMethod()
   2: {
   3:     _dependency.FirstMethod();
   4:     _dependency.ThirdMethod();
   5:     Console.WriteLine("Called ServiceClass.FirstMethod");
   6: }

We check in the changes, run our tests, and boom! Test failed:

 

XunitException: Rhino.Mocks.Exceptions.ExpectationViolationException : IDependency.ThirdMethod(); Expected #0, Actual #1.

 

With strict mocks EVERY single call to the mocked object has to have expectations set on it. If we make an additional call and we don't set the expectation, our test will fail. Our test was to verify the FirstMethod was being called, and it still is. Our test failed because we wrote it using strict mocks, it failed for the wrong reason, and made our code very brittle.

However, if we were to have written the test using Dynamic mocks, this wouldn't happen:

   1: [Fact]
   2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_Dynamic()
   3: {
   4:     MockRepository mocks = new MockRepository();
   5:  
   6:     IDependency dependency = mocks.DynamicMock<IDependency>();
   7:     
   8:     using (mocks.Record())
   9:     {
  10:         dependency.Expect(m => m.FirstMethod()); 
  11:     }
  12:  
  13:     using (mocks.Playback())
  14:     {
  15:         ServiceClass serviceClass = new ServiceClass(dependency);
  16:  
  17:         serviceClass.FirstMethod();
  18:     }
  19:  
  20:     // Note that in the Record/Replay, VerifyAll is implicitly called
  21: }

 

Note that out test is still valid. If we remove the call to Dependency.FirstMethod the test will fail as it should. However, it won't fail if we add additional calls.

An added bonus to using loose mocks with RhinoMocks, is that you can use the AAA (Arrange-Act-Assert) syntax and also call individual expectations. Thus the previous code could be written like so:

   1: [Fact]
   2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_AAA() {
   3:  
   4:     // Arrange
   5:     IDependency dependency = MockRepository.GenerateMock<IDependency>();
   6:  
   7:     dependency.Expect(m => m.FirstMethod());
   8:  
   9:  
  10:     // Act
  11:      ServiceClass serviceClass = new ServiceClass(dependency);
  12:  
  13:     serviceClass.FirstMethod();
  14:  
  15:     // Assert
  16:     dependency.VerifyAllExpectations();
  17:     
  18: }

 

Alternatively, if you don't need expectations to return values, you can just call AssertWasCalled on them:

 

   1: [Fact]
   2: public void ServiceClass_FirstMethod_calls_dependency_FirstMethod_AAA() {
   3:  
   4:     // Arrange
   5:     IDependency dependency = MockRepository.GenerateMock<IDependency>();
   6:  
   7:     // Act
   8:      ServiceClass serviceClass = new ServiceClass(dependency);
   9:  
  10:     serviceClass.FirstMethod();
  11:  
  12:     // Assert
  13:     dependency.AssertWasCalled( m => m.FirstMethod());
  14:     
  15: }

 

Summary

Mocks are a great thing to test behaviour between different components. However, make sure you use them correctly if you don't want to end up with brittle code that any minor change breaks a whole bunch of tests. Strict and ordered mocking should only be used in exceptional cases.