Why Testing Matters in Dart
Dart's testing ecosystem is built around package:test for plain unit tests and package:flutter_test for widget tests, following the classic testing pyramid: many fast unit tests at the base, fewer widget or integration tests above them, and the smallest number of full end-to-end tests at the top.
Cricket analogy: The testing pyramid with many unit tests at the base and few integration tests at the top mirrors a cricket academy running hundreds of net sessions for technique before a handful of full simulated match scenarios.
Writing Unit Tests with package:test
package:test provides test() for individual test cases, group() to organize related tests together, and expect() paired with matchers like equals(), throwsException(), or isA<T>() to assert that actual results match expectations, reporting a clear pass or fail for each case.
Cricket analogy: Grouping related tests with group() in package:test is like organizing net practice into distinct drills — batting technique, bowling accuracy, fielding — each grouped and run separately.
Mocking Dependencies with Mockito
Mockito lets you replace real dependencies, such as an HTTP client or repository, with controllable mock objects. The @GenerateMocks annotation combined with build_runner generates type-safe mock classes, and when() configures a mock's stubbed responses while verify() confirms a method was actually called with the expected arguments.
Cricket analogy: Mocking a network dependency with Mockito is like using a bowling machine set to deliver a specific predictable line and length during batting practice, instead of relying on an unpredictable live bowler.
Widget and Integration Testing in Flutter
Widget tests use testWidgets() and a WidgetTester to build a Flutter widget tree in a fast, headless environment, simulate interactions like taps, and wait for animations to complete with pumpAndSettle() before asserting on the result. For full confidence, the integration_test package runs the whole app on a real device or emulator.
Cricket analogy: pumpAndSettle() waiting for all animations to finish before assertions is like an umpire waiting for the ball to completely stop rolling before confirming a boundary, ensuring the state has fully settled.
import 'package:test/test.dart';
int add(int a, int b) => a + b;
void main() {
group('add()', () {
test('adds two positive integers', () {
expect(add(2, 3), equals(5));
});
test('handles negative numbers', () {
expect(add(-2, -3), equals(-5));
});
test('returns normally for valid input', () {
expect(() => add(2, 3), returnsNormally);
});
});
}
Run dart test --coverage=coverage followed by dart pub global run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --packages=.packages --report-on=lib to generate an lcov coverage report, which tools like genhtml or CI coverage badges can consume to track how much of your codebase is exercised by tests.
- package:test provides test(), group(), and expect() for writing and organizing unit tests in plain Dart.
- The testing pyramid favors many fast unit tests, fewer integration tests, and even fewer full end-to-end tests.
- Mockito lets you replace real dependencies, like network clients, with controllable mock objects using when() and verify().
- @GenerateMocks combined with build_runner generates type-safe mock classes automatically.
- testWidgets() and WidgetTester simulate user interaction with a Flutter widget tree in a fast, headless test environment.
- pumpAndSettle() waits for all animations and async work to finish before assertions run.
- The integration_test package runs full app tests on a real device or emulator, exercising the complete rendering pipeline.
Practice what you learned
1. Which package provides Dart's test(), group(), and expect() functions?
2. What does Mockito's when(...).thenReturn(...) do?
3. What is the purpose of pumpAndSettle() in a widget test?
4. Which package is used to run Flutter integration tests on a real device or emulator?
5. According to the testing pyramid, which type of test should you generally have the most of?
Was this page helpful?
You May Also Like
Dart and JSON Serialization
How to encode and decode JSON in Dart, from manual fromJson/toJson methods to code generation with json_serializable.
Dart and Flutter Overview
An introduction to the Dart language, how it powers Flutter's UI framework, and where else Dart is used beyond mobile app development.
Pub and Package Management
How Dart's pub tool, pubspec.yaml, and the pub.dev registry work together to manage dependencies and publish reusable packages.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics