Preamble
Mocks are surgical instruments. When every collaborator is mocked, tests pass while integration fails—two greens and a broken deploy. I use Mockito in Java and unittest.mock in Python with the same rule: mock boundaries (HTTP, clocks, randomness, message buses), keep domain objects real whenever practical.
What to mock
Network and filesystem
Deterministic tests should not depend on flaky remote services.
Time
Instant.now() and datetime.now() hide race conditions; controlling clocks makes expiry logic testable.
Randomness
Seed or stub RNG when testing lottery-style code paths.
What not to mock
If I mock every method on a domain service, I am testing call order, not behavior. Test Doubles at System Boundaries’s fakes often read better: an in-memory repository implements the same port without brittle verify() chains.
Cross-language consistency
Teams split across Java and Python still share policies: observable outcomes, not internal implementation. Mirror those policies in review checklists so Mockito-heavy Java does not diverge from Python style silently.
Conclusion
Tests that assert too many internal calls couple to refactoring noise. asyncio.gather and Structured Error Handling applies the same boundary thinking to asyncio failure paths.