Why mock the server
- When you want isolate the system under test to ensure tests run reliably and only fail when there is a genuine error, this avoids tests failing due to irrelevant external changes such as network failure or a server being rebooted / redeployed.
- Allows the full range of responses and scenarios to be tested without having to set up and manage a complex test infrastructure. For example increased response delay or dropped connections can increase as load increases on a dependant system. To simulate these types of performance related degradation can be extremely difficult without with out generating a large volume of traffic. If the dependent system is mocked the mock can control the exact response delay or any other characteristics of each response.
- Each test can then independently encapsulate the data and logic used for mock services, ensuring each test runs independently. In addition such an approach also reduces the time for a suite of test to complete because tests can run in parallel and do not share data.
- Allows development teams to isolated from an unstable, unreliable or volatile web service. This is particularly critical during the initial development phases when the APIs / services are changing frequently and cause development and testing to be blocked
Why not mock the server
- Tests can be harder to understand. Instead of just a straightforward usage of your code (e.g. pass in some values to the method under test and check the return result), you need to include extra code to tell the mocks how to behave. Having this extra code detracts from the actual intent of what you’re trying to test, and very often this code is hard to understand if you’re not familiar with the implementation of the production code.
- Tests can be harder to maintain. When you tell a mock how to behave, you’re leaking implementation details of your code into your test. When implementation details in your production code change, you’ll need to update your tests to reflect these changes. Tests should typically know little about the code’s implementation, and should focus on testing the code’s public interface.
- Tests can provide less assurance that your code is working properly. When you tell a mock how to behave, the only assurance you get with your tests is that your code will work if your mocks behave exactly like your real implementations. This can be very hard to guarantee, and the problem gets worse as your code changes over time, as the behavior of the real implementations is likely to get out of sync with your mocks.
- Record and replay real dependent service responses, these recordings are typically complex and shared between multiple tests. This, however, introduces unnecessary coupling between tests and breaks the Single responsibility principle, which, states that every context (class, function, variable, etc.) should define a single responsibility, and that responsibility should be entirely encapsulated by the context.
So, my advice is mock the server, you can mock the server and test the integration in the end of the project (End-to-End tests). Sometimes you can’t use a real dependency in a test (e.g. if it’s too slow or talks over the network), but there may better options than using mocks, such as a hermetic local server (e.g. a credit card server that you start up on your machine specifically for the test) or a fake implementation (e.g. an in-memory credit card server)
Thanks guys, see you next week 🙂