Dart / Flutter test cubit, problem with comparing expected and actual
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.
CoffeeToCodette
Updated on December 01, 2022Comments
-
CoffeeToCodette over 1 year
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); } }
-
CoffeeToCodette about 3 yearsThank you! Actually, WeatherLoaded implements Equatable like in the ResoCoder example. What do I have to change though? I wanted to test if the State is created correctly.
-
edgeboy7 about 3 yearsWhen you extend Equatable, you have to override the props getter and place all the class variables in the list. ``` @override List<Object> get props => [latitude, longitude, temperature]; ```
-
CoffeeToCodette about 3 yearsIt gets autogenerated by Equatable so I already have that. That can't be the problem.
@override List<Object?> get props => [ lat, lon, temperature, ... ];
@override bool? get stringify => true;
-
Paul Pérez over 2 years@Naddle did you find the solution? Im getting the same message.
-
CoffeeToCodette over 2 years@PaulPérez unfortunately, I did not.