You shouldn’t mock all mutable dependencies. To see why, we need to look at two types of communications in a typical application: intra-system and inter-system.

Intra-system communications are communications between classes inside your application

Inter-system communications are when your application talks to other applications.

Here they are on a diagram:

Intra-system and inter-system communications

There’s a huge difference between the two: intra-system communications are implementation details; inter-system communications are not.

Intra-system communications are implementation details because the collaborations your domain classes go through in order to perform an operation are not part of their observable behavior. These collaborations don’t have an immediate connection to the client’s goal. Thus, coupling to such collaborations leads to fragile tests.

Inter-system communications are a different matter. Unlike collaborations between classes inside your application, the way your system talks to the external world forms the observable behavior of that system as a whole. It’s part of the contract your application must hold at all times.

Intra-system communications are implementation details; inter-system communications form the observable behavior of your application as a whole

This attribute of inter-system communications stems from the way separate applications evolve together. One of the main principles of such an evolution is maintaining backward compatibility. Regardless of the refactorings you perform inside your system, the communication pattern it uses to talk to external applications should always stay in place, so that external applications can understand it. For example, messages your application emits on a bus should preserve their structure, the calls issued to an SMTP service should have the same number and type of parameters, and so on.

The use of mocks cements the communication pattern between the system under test and the dependency (makes that pattern harder to change). This is exactly what you want when verifying communications between your system and external applications. Conversely, using mocks to verify communications between classes inside your system couples your tests to implementation details, making them fragile.

Intra-system communications correspond to mutable in-process dependencies:

Intra-system communications are communications with mutable in-process dependencies

And so, the London school is wrong because it encourages the use of mocks for all mutable dependencies and doesn’t differentiate between intra-system (in-process) and inter-system (out-of-process) communications.