पाठ 21 / 25

Testing with package:test and Mocks

Write unit tests, async tests and tests with fakes or mocks.

Fast, reliable tests

package:test is the standard testing library: write test('description', () { ... }) functions grouped with group, use expect(actual, matcher) with matchers such as equals, isTrue, contains, hasLength, throwsA(isA<StateError>()), closeTo and isNull, and set up shared state with setUp and tearDown. Tests can be async: return a Future and await inside, or use expectLater with stream matchers such as emitsInOrder. Run with dart test (and flutter test in Flutter apps), filter with --name, and tag slow tests. Isolate code from dependencies by depending on abstract classes and passing fakes in tests (a FakeGateway implements PaymentGateway), or use mocktail (no code generation) or mockito (with generated mocks) for mocks with when(...).thenAnswer(...) and verify(...). For time-based code, the fake_async package controls timers and microtasks. Measure coverage with dart test --coverage and format it with the coverage package. Flutter adds widget tests and integration tests on top of the same foundations.

Unit tests with a fake and mocktail

Behaviour is checked without real network calls.

import 'package:mocktail/mocktail.dart';
import 'package:test/test.dart';
import 'package:shop/shop.dart';

class MockGateway extends Mock implements PaymentGateway {}

void main() {
  group('PaymentService', () {
    late MockGateway gateway;
    late PaymentService service;

    setUp(() {
      gateway = MockGateway();
      service = PaymentService(gateway);
    });

    test('charges the order total once', () async {
      when(() => gateway.charge(any(), any())).thenAnswer((_) async => 'pay_1');

      final id = await service.pay(orderId: 'o-1', amountPaise: 49900);

      expect(id, equals('pay_1'));
      verify(() => gateway.charge('o-1', 49900)).called(1);
    });

    test('rejects non-positive amounts', () {
      expect(() => service.pay(orderId: 'o-2', amountPaise: 0), throwsA(isA<ArgumentError>()));
    });

    test('streams can be checked in order', () {
      expect(Stream.fromIterable([2, 1, 0]), emitsInOrder([2, 1, 0, emitsDone]));
    });
  });
}

Fakes before mocks

A small hand-written fake (an in-memory repository, a gateway that records calls) is often clearer than many when(...) stubs, and it can be reused across tests.

त्वरित जाँच: Which matcher checks that a function throws a specific error type in package:test?

  • equals
  • isNull
  • throwsA(isA<ArgumentError>())
  • emitsDone
Answer

throwsA(isA<ArgumentError>()) — throwsA with isA<T>() asserts the thrown object's type.