Testing/Mocks

Also see the full, runnable example at the bottom of this page.

Mocking capsules in Dart tests
// I often create useFooBar() methods for disposable resources in my Dart/Flutter tests.
// They compose very similarly to regular side effects.
MockableContainer useContainer() {
  final container = MockableContainer();
  addTearDown(container.dispose);
  return container;
}

(MockableContainer, MockClient) useMockedClientContainer() {
  final mockClient = MockClient();
  final container = useContainer()
    ..mock(httpClientCapsule).apply((use) => mockClient);
  return (container, mockClient);
}

/// Mocked [http.Client] using `mocktail`
class MockClient extends Mock implements http.Client {}

void main() {
  test('fetchWeatherAction returns correct Weather', () async {
    final (container, mockClient) = useMockedClientContainer();

    const latitude = 123.0;
    const longitude = 321.0;
    const temperature = 20.0;
    const weatherCode = 1.0; // = cloudy
    Future<http.Response> expectedCall() => mockClient.get(
          Uri.https('api.open-meteo.com', '/v1/forecast', {
            'latitude': '$latitude',
            'longitude': '$longitude',
            'current_weather': 'true',
          }),
        );
    when(expectedCall).thenAnswer(
      (_) async => http.Response(
        jsonEncode({
          'current_weather': {
            'temperature': temperature,
            'weathercode': weatherCode,
          },
        }),
        200,
      ),
    );

    // fetchWeatherAction will use the `MockClient` we mocked above
    final actualWeather = await container.read(fetchWeatherAction)(
      latitude: latitude,
      longitude: longitude,
    );
    verify(expectedCall).called(1);
    expect(
      actualWeather,
      const Weather(temperature: temperature, weatherCode: weatherCode),
    );
  });
}