tezvyn:

Mocking Dependencies in Flutter with Mockito

AI-drafted, machine-checkedSource: docs.flutter.devintermediate

Mockito creates fake, controllable versions of your app's dependencies, like an API client. This is crucial for unit tests, letting you isolate code from external systems to make tests fast, reliable, and independent of network or database availability.

WHY IT EXISTS When you write a unit test, you want to test a single "unit" of code in isolation. However, code rarely lives in isolation. A class that fetches user data might depend on an HTTP client, which in turn depends on the device's network stack. Testing this class directly would mean making a real network call, which is slow, unreliable, and depends on a live server. Mocking was created to solve this by replacing real dependencies with predictable fakes.

THE MENTAL MODEL Think of a mock object as a stunt double for your real dependency. In a movie, you use a stunt double for dangerous or complex scenes to avoid risking the real actor. In testing, you use a mock object (the stunt double) in place of a real dependency like a database or network client (the real actor). You can program this stunt double to perform specific actions on cue, allowing you to safely and predictably test your main code's reaction.

HOW IT WORKS The mockito package in Dart uses code generation to create a fake version of a class. You first annotate a test file and run a build command, which generates a Mock class. In your test, you instantiate this mock. The key is the when() function: you tell the mock how to behave. For example, you can say, "WHEN your fetchData method is called with the argument '123', THEN return this specific Data object." Your code under test is given this mock instead of the real object. When it calls fetchData('123'), the mock intercepts the call and returns the data you predefined, without ever touching a real database or network.

WHEN TO USE IT Use mocking extensively in unit tests. It's perfect for isolating your business logic from external systems. If you're testing a repository, a BLoC, a ViewModel, or any class that has dependencies, you should mock those dependencies. This makes your tests fast, deterministic (they produce the same result every time), and focused only on the logic you intend to test.

WHEN NOT TO USE IT Do not use mocks for integration tests or end-to-end (e2e) tests. The entire point of those tests is to verify that different parts of your system work together correctly with their real dependencies. Mocking a database connection in an integration test would defeat the purpose. Be wary of over-mocking; if a test requires dozens of mocks to be set up, it might be a sign that your class is doing too much and should be refactored.

ONE CANONICAL EXAMPLE Imagine testing a WeatherService that depends on an ApiClient. Instead of letting it make a real HTTP request, you provide a MockApiClient. In your test's setup phase, you would write something like: when(mockApiClient.get(any)).thenAnswer((_) async => '{"temperature": 72}');. You then call your weatherService.getCurrentTemperature() method. You can then verify that your service correctly called the get method on the client and correctly parsed the fake JSON response to return the number 72.

Read the original → docs.flutter.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.