Excessive Specification of Test Doubles
Tags: unittests, tdd, testing, softwaredesign
Published: 2020-05-20 18:51:05

Previously we’ve discussed the different kinds of [test doubles](https://principal-it.eu/2020/04/test-doubles/). By using test doubles in our solitary tests, we also introduce more coupling between the test code and the implementation. However, the good news is that there are also some things we can do in order to somewhat reduce this coupling.

A very important item of caution is to avoid excessive specification of method behaviour. Let’s have a look at an example.

```csharp
var approverId = new Guid("224FE5B8-EDBB-4F8B-8654-715C1C294CFD");
HeadOfDepartment headOfDepartment = Example.HeadOfDepartment().WithId(approverId);

var approverRepositoryMock = Substitute.For<IApproverRepository>();
approverRepositoryMock.Received().Get(approverId).Returns(headOfDepartment);
```

Here we create a mock for the _IApproverRepository_ interface, created by the NSubstitute framework. When the subject under test makes a call to the _Get_ method using a specific identifier, then an instance of the _HeadOfDepartment_ is returned. However, that’s not the only thing that happens. The mock also verifies whether the subject under test actually makes a call to the _Get_ method. If not, then the test will fail. The approach taken in this example illustrates the concept of excessive specification.

With behaviour verification, the degree of coupling between the test code and the implementation depends on the type of test double being used. Using a _Dummy_ or a _Stub_ results in the least amount of coupling, while using a _Spy_ or a _Mock_ induces the highest amount of coupling.

For indirect inputs, as is the case in our example, we should avoid using mocks at all times. We should use stubs instead. Let’s have a look at an improved version of the previous example.

```csharp
HeadOfDepartment headOfDepartment = Example.HeadOfDepartment()
    .WithId(new Guid("224FE5B8-EDBB-4F8B-8654-715C1C294CFD"));

var approverRepositoryStub = Substitute.For<IApproverRepository>();
approverRepositoryStub.Get(Guid.Empty).ReturnsForAnyArgs(headOfDepartment);
```

Here we no longer verify whether the _Get_ method is being called. We only state that whenever the _Get_ method of the _ApproverRepository_ is called, no matter what the identifier might be, just return the specified _HeadOfDepartment_ object. So we basically switched from using a mock to using a stub.

For solitary tests that make use of test doubles, prefer the use of stubs over spies and mocks. Generalisation of stub method arguments make solitary tests more resilient to changes. I always try to use the most generic argument matcher that is feasible for a particular scenario.

Obviously, we sometimes need to use spies or mocks. For those cases, it’s very important to restrict their use to only verifying indirect outputs. We should only specify what should happen and nothing more.

The following piece of test code is an example where the use of a mock is warranted.

```csharp
[Observation]
public void Then_the_approved_expense_sheet_should_be_saved()
{
    _expenseSheetRepositoryMock.Received().Save(_expenseSheet);
}
```

When observing solitary tests that make use of test doubles in a decent code base, you might see that the usage ratio of dummies and/or stubs is significantly higher than that of spies and/or mocks. This should give us a decent idea about the usage of the different types of test doubles.