Dart / Flutter test cubit, problem with comparing expected and actual

3.6k views Asked by At

I'm working on an app using a WeatherAPI. I currently fail to implement some working tests. I tried to follow ResoCoders Guide (https://resocoder.com/2019/11/29/bloc-test-tutorial-easier-way-to-test-blocs-in-dart-flutter/) and actually implemented all states, blocs (I used Cubit instead), classes, functions, ... almost the same.

This is my test's code:

blocTest<WeatherCubit, WeatherBaseState>(
      'Cubit emits WeatherLoaded',
      build: () {
        return WeatherCubit(weatherRepository: mockWeatherRepository);
      },
      act: (WeatherCubit cubit) => cubit.getWeather(),
      expect: () => [
        WeatherLoaded(
            temperature: temperature,
            ...
            lat: lat,
            lon: lon)
      ],
    );

And that's my error massage from the debug console:

Expected: [Instance of 'WeatherLoaded']
  Actual: [Instance of 'WeatherLoaded']
   Which: at location [0] is <Instance of 'WeatherLoaded'> instead of <Instance of 'WeatherLoaded'>

WARNING: Please ensure state instances extend Equatable, override == and hashCode, or implement Comparable.
Alternatively, consider using Matchers in the expect of the blocTest rather than concrete state instances.

I tried to use a Matcher but did not quite get how to use it.

In case the problem lies here, my implementation of the WeatherCubit:

class WeatherCubit extends Cubit<WeatherBaseState> {
  final IWeatherRepository weatherRepository; //IWeatherRepository is interface

  WeatherCubit({required this.weatherRepository})
      : super(LoadingWeather()); // I use LoadingWeather as initial state


  Future<void> getWeather() async {
    final Position location = await weatherRepository.determinePosition();
    final WeatherData data = await weatherRepository.getWeather(
        lat: location.latitude, 
        lon: location.longitude); 
    final WeatherLoaded weatherLoaded = WeatherLoaded(
        temperature: data.temperature,
        ...
        lat: data.lat, 
        lon: data.lon); 
    emit(weatherLoaded); 
  }
}
2

There are 2 answers

5
edgeboy7 On

You can use the isA matcher if you are trying to test the type.

expect: () => [isA<WeatherLoaded>()];

If you are trying to compare the values of the returned object you need to either use the Equatable package, or manually override the hashCode and == operator in your Cubit.

0
Shan On

As mentioned above you can use the isA, matcher. To check the properties, try using the having method available in this matcher.

 expect: () => [isA<WeatherLoaded>()..having((p0) => p0.temprature, "description", "30")];

Here "30" is the expected value.

Like this, you can check all the properties.