Here are some interesting ideas about structuring code so that tests don't have to rely on mocks. From [Testing Without Mocks: A Pattern Language](https://www.jamesshore.com/v2/blog/2018/testing-without-mocks): > When programmers use test-driven development (TDD), the code they test interacts with other parts of the system that aren’t being tested. To test those interactions, and to prevent the other code from interfering with their tests, programmers often use [mock objects](https://martinfowler.com/articles/mocksArentStubs.html) or other test doubles. However, this approach requires additional integration tests to ensure the system works as a whole, and it can make structural refactorings difficult. > > This pattern language describes a way of testing object-oriented code without using mocks. It avoids the downsides of mock-based testing, but it has tradeoffs of its own. > ... > These patterns are an effective way of writing code that can be tested without test doubles, DI frameworks, or end-to-end tests.