Loose vs. Strict mocking behaviour

I thought I would demonstrate the difference between Loose and Strict mocking behaviour when using the Moq Framework. By default when you create a new mock and don't specify a MockBehaviour it will be assigned MockBehaviour.Default, which equals to MockBehaviour.Loose:

"Will never throw exceptions, returning default values when necassary (null for reference types, zero for value types or empty for enumerables and arrays)."

Another alternative is to use MockBehaviour.Strict:

"Causes the mock to always throw exceptions for invocations that don't have a corresponding setup."

The differences might sound obvious, but I find that it's always easier to understand when you put it in a context and here is a super simplified scenario.

A service:

This is the service interface which we will create a mock from:

public interface ISomeService
{
string SomeMethod(string parameter);
string SomeOtherMethod();
}

 

A SUT:

This is our SUT (System Under Test) that will consume the mocked serviced. Notice that the Index method invokes both methods from the service (this is important!).

public string Index()
{
    var something = this.service.SomeMethod("something");
    var somethingElse = this.service.SomeOtherMethod();
    return $"{something}-{somethingElse}";
}

 

A test:

Now imagine that we have this test where we setup the return value of SomeMethod("something") but we don't setup SomeOtherMethod() even though it is also used by the SUT.

// Arrange
var service = new Mock<ISomeService>();
service.Setup(x => x.SomeMethod("something")).Returns("any");
var sut = new Controller(service.Object);
// Act
var result = sut.Index();
// Assert
Assert.That(result, Is.EqualTo("any-"));



The result:

Using the default (Loose) behaviour this test will pass since the SomeOtherMethod() is going to return null. But if we use the exact same code and test, except we create our mock with a Strict behaviour this test will fail. This is because the Strict behaviour expects SomeOtherMethod() to also be setup since it is used by the SUT.

var service = new Mock<ISomeService>(MockBehavior.Strict);

To make our strict test pass you need to also setup SomeOtherMethod() and assign a return value, for example using something like this: 

// Arrange
var service = new Mock<ISomeService>(MockBehavior.Strict);
service.Setup(x => x.SomeMethod("something")).Returns("any");
service.Setup(x => x.SomeOtherMethod()).Returns("thing");
var sut = new Controller(service.Object);
// Act
var result = sut.Index();
// Assert
Assert.That(result, Is.EqualTo("any-thing"));

And there you have it! ✅

Summary:

In this example I used a non-setup method to demonstrate the strict behaviour but as you might have guessed this also applies to properties where the loose behaviour will assign empty arrays, 0 for integers/decimals etc. whereas the strict will fail if you reference any properties in your mock which has not been setup.

There is no right or wrong behaviour here, totally up to you. It seems like there is a lot of debate in this question with equally large teams. Some prefer loose since it requires less mocking whereas some prefer strict since they consider it to be more true and explicit.

Personally, I'm a Loose kind of guy. 😎

I should also mention that FakeItEasy, which is another mocking framework, supports Strict behaviour but NSubstitute does not seem to (without haching) according to their documentation (which seems to be a highly requested feature).

Cheers friends! ❤️