An unmanaged dependency is an out-of-process dependency that the application does not fully control and whose interactions are externally observable. SMTP servers and message buses are typical examples: their side effects can be seen by other applications, so their communication forms part of the system’s observable behavior. section 8.2
Classify each out-of-process dependency before choosing how an integration test should handle it:
- Replace an unmanaged dependency with a mock, preserving and checking the communication pattern that external systems rely on. section 8.2
- Use a real managed dependency, such as an application-only database, and verify its final state rather than its interactions. section 8.2
- Split mixed dependencies by visibility: mock the externally visible portion of a database and verify the remainder through final-state assertions. section 8.8
- Mock only the last type at the system edge, where the application’s adapter communicates with the external dependency; this protects the external contract without coupling tests to intermediate wrappers. section 9.1 section 9.3
Changing a user’s email
An integration test inserts a user and company into a real database, runs the change-email scenario, verifies the database state, and replaces the message bus with a test double. A stronger version constructs the production message-bus adapter around a mocked IBus, then verifies the exact emitted message once. A handwritten BusSpy can make the assertion shorter and more readable. section 8.3 section 9.1
Figure 8.4. Communications with managed dependencies are implementation details; use such dependencies as-is in integration tests. Communications with unmanaged dependencies are part of your system’s observable behavior. Such dependencies should be mocked out.
Use the dependency boundary to distinguish implementation details from externally observable communication. section 8.2
Figure 8.5. Treat the part of the database that is visible to external applications as an unmanaged dependency. Replace it with mocks in integration tests. Treat the rest of the database as a managed dependency. Verify its final state, not interactions with it.
Apply separate treatment when only part of a database is visible to external applications. section 8.2
