An adapter places a replaceable interface around a dependency. For asynchronous code, it hides operations such as fetching a URL behind simpler functions, allowing production code to use the real dependency while tests substitute a controlled fake. section 6.2.2 section 6.6
Choose the adapter shape that best fits the code and test design:
- Modular adapters wrap a whole module; tests replace selected functions with mocks. section 6.6
- Functional adapters accept an injected function or value, which tests replace with a stub. section 6.6
- Object-oriented adapters define an interface in production code and provide a test implementation that satisfies it. section 6.6
- A focused interface can expose only the operations the consumer needs, hiding an underlying dependency's larger API and complexity. section 6.2.2
Wrapping a network dependency
Keep the real network library inside one adapter module: const fetch = require("node-fetch"); const fetchUrlText = async (url) => { const response = await fetch(url); if (response.ok) { return { ok: true, text: await response.text() }; } return { ok: false, text: response.statusText }; }; module.exports = { fetchUrlText }; Application code calls network.fetchUrlText(url), while a Jest test can mock that module and return good, bad, or unexpected content without performing a real request. This improves control and speed, but changes to the underlying fetching dependency may require updating the adapter's contract and its consumers' assumptions. section 6.2.2 section 6.6
Figure 6.7 Wrapping the node-fetch module with our own network-adapter module helps us expose only the functionality our application needs, expressed in the language most suitable for the problem at hand.
Inspect how a network adapter exposes application-specific functionality while hiding the underlying fetch API. section 6.2.2








