Testing and Mocking Dart Applications
Contents
Structuring Code for Testability
Managing Dependencies
Generating Mocks
Implementing Unit Tests
Workflow: Creating and Running Mocked Tests
Examples
Structuring Code for Testability
Design Dart classes to support dependency injection. Isolate complex external dependencies (like API clients or databases) so they can be replaced with mock objects during testing.
Inject external services (e.g.,
http.Client
) through class constructors.
Represent URLs strictly as
Uri
objects using
Uri.parse(string)
.
Utilize Dart's object-oriented features (classes, mixins) to define clear interfaces for external interactions.
Managing Dependencies
Configure the
pubspec.yaml
file with the necessary testing and code generation packages.
Add runtime dependencies (e.g.,
package:http
) using
dart pub add http
.
Add testing dependencies using
dart pub add dev:test dev:mockito dev:build_runner
.
Import HTTP libraries with a prefix to avoid namespace collisions:
import 'package:http/http.dart' as http;
.
Generating Mocks
Use
package:mockito
and
build_runner
to automatically generate mock classes for fixed scenarios and behavior verification.
Always use the
@GenerateNiceMocks
annotation (preferable to
@GenerateMocks
to avoid missing stub exceptions).
Place the annotation in the test file, passing a list of
MockSpec
fetchData ( String urlString ) async { final uri = Uri . parse ( urlString ) ; final response = await client . get ( uri ) ; if ( response . statusCode == 200 ) { return jsonDecode ( response . body ) [ 'data' ] ; } else { throw Exception ( 'Failed to load data' ) ; } } } 2. Test Implementation ( test/api_service_test.dart ) import 'package:test/test.dart' ; import 'package:mockito/annotations.dart' ; import 'package:mockito/mockito.dart' ; import 'package:http/http.dart' as http ; import 'package:my_app/api_service.dart' ; // Generate the mock class for http.Client @GenerateNiceMocks ( [ MockSpec < http . Client
( ) ] ) import 'api_service_test.mocks.dart' ; void main ( ) { group ( 'ApiService' , ( ) { late ApiService apiService ; late MockClient mockHttpClient ; setUp ( ( ) { mockHttpClient = MockClient ( ) ; apiService = ApiService ( mockHttpClient ) ; } ) ; test ( 'returns data if the http call completes successfully' , ( ) async { // Arrange: Stub the async HTTP GET request using thenAnswer when ( mockHttpClient . get ( any ) ) . thenAnswer ( ( _ ) async =
http . Response ( '{"data": "Success"}' , 200 ) , ) ; // Act final result = await apiService . fetchData ( 'https://api.example.com/data' ) ; // Assert expect ( result , 'Success' ) ; // Verify the mock was called with the correct Uri verify ( mockHttpClient . get ( Uri . parse ( 'https://api.example.com/data' ) ) ) . called ( 1 ) ; } ) ; test ( 'throws an exception if the http call completes with an error' , ( ) { // Arrange when ( mockHttpClient . get ( any ) ) . thenAnswer ( ( _ ) async =
http . Response ( 'Not Found' , 404 ) , ) ; // Act & Assert expect ( apiService . fetchData ( 'https://api.example.com/data' ) , throwsException , ) ; } ) ; } ) ; }