简体   繁体   English

在 mapEventToState 中使用 yield 和 Either 时测试我的集团失败

[英]Testing my bloc fails when using yield and Either in the mapEventToState

I'm following a course on clean architecture and I'm stuck with the following error.我正在学习有关干净架构的课程,但遇到以下错误。

The following test fails.以下测试失败。

test('should emit [Error] when the input is invalid', () async {
  final tNumberString = '1';
  when(mockInputConverter.stringToUnsignedInteger(any))
    .thenReturn(Left(InvalidInputFailure()));

  final expected = [
    Empty(),
    Error(message: invalidInput),
   ];
   expectLater(bloc.state, emitsInOrder(expected));

   bloc.add(GetTriviaForConcreteNumberEvent(tNumberString));
});

My NumberTriviaBloc is as follows我的 NumberTriviaBloc 如下

part 'number_trivia_event.dart';
part 'number_trivia_state.dart';

const String serverFailureMessage = 'Server Failure';
const String cacheFailureMessage = 'Cache Failure';
const String invalidInput =
    'Invalid input - the number should be a positive integer';

class NumberTriviaBloc extends Bloc<NumberTriviaEvent, NumberTriviaState> {
  NumberTriviaBloc(
      {@required GetConcreteNumberTrivia concrete,
      @required GetRandomNumberTrivia random,
      @required this.inputConverter})
      : assert(concrete != null),
        assert(random != null),
        assert(inputConverter != null),
        _getConcreteNumberTrivia = concrete,
        _getRandomNumberTrivia = random,
        super(Empty());

  final GetConcreteNumberTrivia _getConcreteNumberTrivia;
  final GetRandomNumberTrivia _getRandomNumberTrivia;
  final InputConverter inputConverter;

  @override
  Stream<NumberTriviaState> mapEventToState(
    NumberTriviaEvent event,
  ) async* {
    if (event is GetTriviaForConcreteNumberEvent) {
      final inputEither =
          inputConverter.stringToUnsignedInteger(event.numberString);

      yield* inputEither.fold(
        (l) async* {
          yield Error(message: invalidInput);
        },
        (r) => throw UnimplementedError(),
      );
    }
  }
}

Im not that familiar with the bloc patern and the testing mechanisms of streams and states.我不太熟悉 bloc 模式以及流和状态的测试机制。 Im guessing somehow the code isn't executed correctly because the fail message is as follows我猜不知何故代码没有正确执行,因为失败消息如下

ERROR: Expected: should do the following in order:
emit an event that Empty:<Empty>
emit an event that Error:<Error>
Actual: Empty:<Empty>
Which: was not a Stream or a StreamQueue

So I solved it my self.所以我自己解决了。 The code in the question is valid for older versions of dart.问题中的代码对旧版本的 dart 有效。 At present目前

bloc.state

will break the code.会破解密码。 Instead反而

bloc

should be used to get the state.应该用于获取状态。

The second problem is that it's no longer possible to have a第二个问题是不再可能有一个

throw UnimplementedError();

in the fold method of the Either object.在Either 对象的fold 方法中。 That will cause an exception to be thrown in either case.这将导致在任何一种情况下抛出异常。 There has to be some non exception logic in the right function of the fold call.在 fold 调用的正确函数中必须有一些非异常逻辑。

The modifications are reflected in the code below.修改反映在下面的代码中。

number_trivia_bloc_test.dart number_trivia_bloc_test.dart

test('should emit [Error] when the input is invalid', () async {
  when(mockInputConverter.stringToUnsignedInteger(any))
      .thenReturn(Left(InvalidInputFailure()));

  bloc.add(GetTriviaForConcreteNumberEvent(tNumberString));

  final expected = [
    Error(message: invalidInput),
  ];
  expectLater(bloc, emitsInOrder(expected));
});

number_trivia_bloc.dart number_trivia_bloc.dart

@override
Stream<NumberTriviaState> mapEventToState(NumberTriviaEvent event,
  ) async* {
  if (event is GetTriviaForConcreteNumberEvent) {
    final inputEither =
      inputConverter.stringToUnsignedInteger(event.numberString);

    yield* inputEither.fold(
      (failure) async* {
        yield Error(message: invalidInput);
      },
      (integer) async* {
        yield null;
      },
    ); 
  }
}

You solution did not work for me but gave me something to work on.你的解决方案对我不起作用,但给了我一些工作。 All I did was change bloc to bloc.stream and then remove Empty() from the list.我所做的只是将 bloc 更改为 bloc.stream,然后从列表中删除 Empty()。

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

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