FLUTTER:测试 cubit 时,不会发出加载状态,只会发出加载状态
FLUTTER: When testing cubit, loading state isn't emitted, only loaded state is
当我 运行 我的应用程序正常时,我执行 cubit.getWeather('London')
并且 weatherLoading 状态发出,然后 weatherLoaded 状态正确发出。
然而,当我 运行 测试 cubit 以测试 cubit.getWeather('London')
时,weatherLoading 状态没有发出 - 它直接跳转到 weatherLoaded 状态。
为什么会这样?
州:
@freezed
abstract class WeatherState with _$WeatherState {
factory WeatherState.weatherInitial() = WeatherInitial;
factory WeatherState.weatherLoading() = WeatherLoading;
factory WeatherState.weatherLoaded(Weather weather) = WeatherLoaded;
factory WeatherState.weatherError(String message) = WeatherError;
}
肘:
class WeatherCubit extends Cubit<WeatherState> {
final WeatherRepository _weatherRepository;
static Weather weather;
WeatherCubit(this._weatherRepository) : super(WeatherState.weatherInitial());
Future<void> getWeather(String cityName) async {
emit(WeatherState.weatherLoading());
try {
final weather = await _weatherRepository.fetchWeather(cityName);
emit(WeatherState.weatherLoaded(weather));
} on NetworkException {
emit(WeatherState.weatherError("Network error"));
}
}
}
我的天气资料库 class 有 'Future<Weather> fetchWeather(String cityname){...}'
方法。
最后,我的测试:
class MockWeatherRepository extends Mock implements WeatherRepository {}
void main() {
MockWeatherRepository mockWeatherRepository;
WeatherCubit cubit;
final weather = Weather(cityName: 'London', temperatureCelsius: 7);
setUp(() {
mockWeatherRepository = MockWeatherRepository();
when(mockWeatherRepository.fetchWeather(any))
.thenAnswer((_) async => weather);
cubit = WeatherCubit(mockWeatherRepository);
});
test(
'emits [WeatherLoading, WeatherLoaded] when successful',
() async {
cubit.getWeather('London');
await expectLater(
cubit,
emitsInOrder([ //Fails
WeatherState.weatherLoading(),
WeatherState.weatherLoaded(weather),
]),
);
},
);
}
停顿了一天,找到了解决办法。
将 expectLater 放在肘“act”之前。
正如我从 resoCoder 中读到的一个集团的例子:
It is usually not be necessary to call expectLater before actually dispatching the event because it takes some time before a Stream emits its first value. I like to err on the safe side though.
我想这对 cubits 来说是不正确的,你应该总是在调用 cubit 上的方法之前调用 expectLater。
test(
'emits [WeatherLoading, WeatherLoaded] when successful',
() {
expectLater(
cubit,
emitsInOrder([ //Fails
WeatherState.weatherLoading(),
WeatherState.weatherLoaded(weather),
]),
);
cubit.getWeather('London');
},
);
另一种方法,来自阅读bloc_test:
您可以使用 blocTest:
blocTest creates a new cubit-specific test case with the given
description. blocTest will handle asserting that the cubit emits the
expected states (in order) after act is executed. blocTest also
handles ensuring that no additional states are emitted by closing the
cubit stream before evaluating the expectation.
在我的例子中,将测试移至 bloctest 就像我预期的那样工作。
blocTest('emits [WeatherLoading, WeatherLoaded] when successful',
build: () => WeatherCubit(mockWeatherRepository),
act: (WeatherCubit cubit) {
when(mockWeatherRepository.fetchWeather(any)).thenAnswer((_) => weather);
cubit.getWeather('London');
},
expect: [
WeatherState.weatherLoading(),
WeatherState.weatherLoaded(weather),
]);
当我 运行 我的应用程序正常时,我执行 cubit.getWeather('London')
并且 weatherLoading 状态发出,然后 weatherLoaded 状态正确发出。
然而,当我 运行 测试 cubit 以测试 cubit.getWeather('London')
时,weatherLoading 状态没有发出 - 它直接跳转到 weatherLoaded 状态。
为什么会这样?
州:
@freezed
abstract class WeatherState with _$WeatherState {
factory WeatherState.weatherInitial() = WeatherInitial;
factory WeatherState.weatherLoading() = WeatherLoading;
factory WeatherState.weatherLoaded(Weather weather) = WeatherLoaded;
factory WeatherState.weatherError(String message) = WeatherError;
}
肘:
class WeatherCubit extends Cubit<WeatherState> {
final WeatherRepository _weatherRepository;
static Weather weather;
WeatherCubit(this._weatherRepository) : super(WeatherState.weatherInitial());
Future<void> getWeather(String cityName) async {
emit(WeatherState.weatherLoading());
try {
final weather = await _weatherRepository.fetchWeather(cityName);
emit(WeatherState.weatherLoaded(weather));
} on NetworkException {
emit(WeatherState.weatherError("Network error"));
}
}
}
我的天气资料库 class 有 'Future<Weather> fetchWeather(String cityname){...}'
方法。
最后,我的测试:
class MockWeatherRepository extends Mock implements WeatherRepository {}
void main() {
MockWeatherRepository mockWeatherRepository;
WeatherCubit cubit;
final weather = Weather(cityName: 'London', temperatureCelsius: 7);
setUp(() {
mockWeatherRepository = MockWeatherRepository();
when(mockWeatherRepository.fetchWeather(any))
.thenAnswer((_) async => weather);
cubit = WeatherCubit(mockWeatherRepository);
});
test(
'emits [WeatherLoading, WeatherLoaded] when successful',
() async {
cubit.getWeather('London');
await expectLater(
cubit,
emitsInOrder([ //Fails
WeatherState.weatherLoading(),
WeatherState.weatherLoaded(weather),
]),
);
},
);
}
停顿了一天,找到了解决办法。
将 expectLater 放在肘“act”之前。
正如我从 resoCoder 中读到的一个集团的例子:
It is usually not be necessary to call expectLater before actually dispatching the event because it takes some time before a Stream emits its first value. I like to err on the safe side though.
我想这对 cubits 来说是不正确的,你应该总是在调用 cubit 上的方法之前调用 expectLater。
test(
'emits [WeatherLoading, WeatherLoaded] when successful',
() {
expectLater(
cubit,
emitsInOrder([ //Fails
WeatherState.weatherLoading(),
WeatherState.weatherLoaded(weather),
]),
);
cubit.getWeather('London');
},
);
另一种方法,来自阅读bloc_test: 您可以使用 blocTest:
blocTest creates a new cubit-specific test case with the given description. blocTest will handle asserting that the cubit emits the expected states (in order) after act is executed. blocTest also handles ensuring that no additional states are emitted by closing the cubit stream before evaluating the expectation.
在我的例子中,将测试移至 bloctest 就像我预期的那样工作。
blocTest('emits [WeatherLoading, WeatherLoaded] when successful',
build: () => WeatherCubit(mockWeatherRepository),
act: (WeatherCubit cubit) {
when(mockWeatherRepository.fetchWeather(any)).thenAnswer((_) => weather);
cubit.getWeather('London');
},
expect: [
WeatherState.weatherLoading(),
WeatherState.weatherLoaded(weather),
]);