Normal (or loose) mocks are used when you want to verify that an expected method has been called with the proper parameters.
Strict mocks are used to verify that only the expected methods have been called and no other. Think of them as a kind of negative test.
In most cases, having strict mocks makes your unit tests very fragile. Tests start failing even if you make a small internal implementation change.
But let me give you an example where they may be useful - testing a requirement such as:
"A Get on a cache should not hit the database if it already contains data".
There are ways to achieve this with loose mocks, but instead, it is very convenient to simply set up a strict Mock<Database>
with zero expected function calls. Any call to this database will then throw an exception and fail the test.
Another scenario where you would want to use strict mocks is in an Adapter
or Wrapper
design pattern. In this pattern, you are not executing much business logic. The major part of testing these classes is whether the underlying functions have been called with the correct parameters (and no other). Strict mocks work fairly well in this case.