I've been trying to understand when to mock and when not to mock, however I'm not able to come up with a consistent guideline and I'm hoping to get some input on the subject. Let's look at the following toy example:
class ServiceMixer: def __init__(...): self._expensive_rpc_service = ExpensiveRPCService(...) self._db_scan_service = DBScanService(...) self._cpu_intensive_computation_service = ExpensiveCPUService(...) def get_results(input): result_1 = self._expensive_rpc_service(input) result_2 = self._db_scan_service(input) result_3 = self._cpu_intensive_computation_service(input) return compute_output(result_1, result_2, result_3)
I want to now write unit-tests on the
get_results method. I do understand that in this example, I will need to use a mock somewhere regardless - two of the services have side-effects (i.e. they talk to a DB or make an RPC to another service). The question is, should I mock the 3 services shown here, or should I mock the RPC calls and the DB calls that the services make in the ServiceMixer unit tests?
One advantage of mocking just the RPC / DB Calls is that I can test the contracts between the difference services and the ServiceMixer. If a downstream service changes, then the service mixer test will break. This is somewhat like an integration test. On the other hand, it will mean that the unit tests for get_results need to innately understand the nuances of how each service works so it can correctly place expectations of the arguments + returned values.
If I were to just mock the services here, then I can just focus on testing the behavior of the ServiceMixer, but I will then miss out the caller-callee contract testing. So, what is the best practice here? It seems like using mocks is the right approach, but I've seen a few articles that state "too many mocks are a code-smell". When is it appropriate to use a mock? When is it not?