Dependency Injection: Swapping Services for Smarter Testing
In this lesson, you’ll learn how to use Dependency Injection (DI) to swap real native services with mock versions so your unit tests remain fast, reliable, and independent of actual hardware.
Why Do We Need DI?
Imagine your app uses a BluetoothScanner native module. If you try to run unit tests, the test suite might fail because it can't find a real Bluetooth radio, or it might accidentally try to connect to nearby devices. Dependency Injection solves this by "injecting" the dependency into your code rather than hard-coding it. This allows you to swap the real module for a "mock" one during testing without changing your business logic.
Implementing the Pattern
Instead of importing a native module directly inside a component, we pass the service as an argument (or via a provider).
1. The Service Interface Create a standard structure for your service:
// BluetoothService.js
export const BluetoothService = {
scan: () => NativeModules.BluetoothScanner.scan(),
};
2. The Injection Pass the service into your component or business logic function:
export const startScanning = (service = BluetoothService) => {
return service.scan();
};
3. The Test Swap When writing your unit tests, you don't need the real native bridge. You simply pass a "mock" object that looks like the real service:
// Bluetooth.test.js
test('should scan for devices', () => {
const mockService = {
scan: jest.fn(() => Promise.resolve(['Device A'])),
};
const result = startScanning(mockService);
expect(mockService.scan).toHaveBeenCalled();
});
By decoupling the service from your logic, your code no longer cares if it is talking to a complex piece of hardware or a simple object in your test file. This makes your test suite portable and prevents native bridge crashes during automated test runs. By keeping your dependencies loose, you gain full control over the environment in which your code executes.
Key Takeaway: Dependency Injection allows you to substitute real native modules with lightweight mocks, ensuring your business logic is testable in isolation without requiring actual hardware components.