简体   繁体   English

FLUTTER:测试cubit时,不发出加载状态,只有加载状态

[英]FLUTTER: When testing cubit, loading state isn't emitted, only loaded state is

When I run my app normally, I execute cubit.getWeather('London') and the weatherLoading state emits, then weatherLoaded state emits CORRECTLY.当我正常运行我的应用程序时,我执行cubit.getWeather('London')并且 weatherLoading 状态发出,然后weatherLoaded 状态发出正确的。

However when I run test for the cubit to test cubit.getWeather('London') , the weatherLoading state isn't emitted - it jumps straight to weatherLoaded state.但是,当我为 cubit 运行 test 以测试cubit.getWeather('London') ,不会发出 weatherLoading 状态 - 它直接跳转到 weatherLoaded 状态。

Why is this happening?为什么会这样?

State:状态:

@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;
}

Cubit:肘:

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"));
    }
  }
}

My weather repository class has 'Future<Weather> fetchWeather(String cityname){...}' method.我的天气存储库类有'Future<Weather> fetchWeather(String cityname){...}'方法。

And finally, my test:最后,我的测试:

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),
        ]),
      );
    },
  );
}

After a day of pause, I found a solution.经过一天的停顿,我找到了解决办法。 Put the expectLater before the cubit "act".将 expectLater 放在肘“行为”之前。
As i read from resoCoder as example of a bloc:正如我从 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.通常没有必要在实际调度事件之前调用 expectLater,因为在 Stream 发出它的第一个值之前需要一些时间。 I like to err on the safe side though.不过,我喜欢在安全方面犯错。

I guess this is not true for cubits and you should always call expectLater before calling the method on the cubit.我猜这不适用于 cubits,您应该始终在调用 cubit 上的方法之前调用 expectLater。

test(
'emits [WeatherLoading, WeatherLoaded] when successful',
  () {
    expectLater(
      cubit,
      emitsInOrder([ //Fails
        WeatherState.weatherLoading(),
        WeatherState.weatherLoaded(weather),
      ]),
    );
    cubit.getWeather('London');
  },
);

Alternative approach, from reading bloc_test: You can use blocTest:另一种方法,从阅读 bloc_test: 您可以使用 blocTest:

blocTest creates a new cubit-specific test case with the given description. blocTest 使用给定的描述创建一个新的特定于肘的测试用例。 blocTest will handle asserting that the cubit emits the expected states (in order) after act is executed. blocTest 将处理断言 cubit 在执行后发出预期状态(按顺序)。 blocTest also handles ensuring that no additional states are emitted by closing the cubit stream before evaluating the expectation. blocTest 还通过在评估期望值之前关闭 cubit 流来确保不会发出额外的状态。

In my case just moving the test to bloctest worked like i expected the test to work.在我的情况下,只是将测试移动到 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),
  ]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM