Testing

37.1 package:test

// test/calculator_test.dart
import 'package:test/test.dart';
import 'package:my_app/calculator.dart';

void main() {
  late Calculator calc;

  setUp(() => calc = Calculator());
  tearDown(() {});

  group('Calculator', () {
    test('adds two numbers', () {
      expect(calc.add(2, 3), equals(5));
    });

    test('throws on division by zero', () {
      expect(() => calc.divide(1, 0), throwsA(isA<ArgumentError>()));
    });

    test('async result', () async {
      expect(await calc.fetchRemoteValue(), greaterThan(0));
    });

    test('stream emits values', () {
      expect(Stream.fromIterable([1, 2, 3]), emitsInOrder([1, 2, 3, emitsDone]));
    });

    test('collections', () {
      expect([3, 1, 2]..sort(), orderedEquals([1, 2, 3]));
      expect({'a': 1}, containsPair('a', 1));
      expect('hello world', allOf(startsWith('hello'), contains('wor')));
      expect(3.14159, closeTo(3.14, 0.01));
    }, tags: ['unit']);

    test('skipped', () {}, skip: 'Not implemented yet');
  });
}
dart test
dart test --name "adds"
dart test -p chrome                  # run tests in a browser
dart test --coverage=coverage && dart pub global run coverage:format_coverage --lcov -i coverage -o lcov.info

37.2 Mocking

mockito (code-generated mocks with @GenerateMocks) and mocktail (no codegen) are both popular. fake_async controls time in tests. clock gives you injectable time. checks offers a newer assertion API.

Flutter adds widget tests (testWidgets, WidgetTester), golden tests, and integration tests (integration_test, Patrol).

import 'package:mocktail/mocktail.dart';

class MockApiClient extends Mock implements ApiClient {}

void main() {
  test('repository returns users from the API', () async {
    final api = MockApiClient();
    when(() => api.getUsers()).thenAnswer((_) async => [User(id: 1, name: 'Ana')]);

    final repo = UserRepository(api);
    final users = await repo.loadUsers();

    expect(users, hasLength(1));
    verify(() => api.getUsers()).called(1);
  });
}

37.3 Testing Best Practices

Follow the Arrange-Act-Assert pattern. Test behavior through public APIs. Inject dependencies (clients, clocks, random). Keep tests fast and deterministic. Use tags to separate integration tests. Aim for meaningful coverage.