flutter - 在 mapEventToState 中使用 yield 和 Either 时测试我的块失败
问题描述
我正在学习有关清洁架构的课程,但遇到以下错误。
以下测试失败。
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));
});
我的 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(),
);
}
}
}
我不太熟悉 bloc 模式以及流和状态的测试机制。我以某种方式猜测代码没有正确执行,因为失败消息如下
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
解决方案
所以我自己解决了。问题中的代码对旧版本的 dart 有效。现在
bloc.state
会破坏代码。反而
bloc
应该用来获取状态。
第二个问题是不再可能拥有
throw UnimplementedError();
在 Either 对象的 fold 方法中。这将导致在任何一种情况下都抛出异常。fold 调用的正确函数中必须有一些非异常逻辑。
修改反映在下面的代码中。
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
@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;
},
);
}
}
推荐阅读
- c# - 如何查看 Azure 服务总线队列中的所有消息?
- node.js - 如何在 Paypal 上制作和支付订单
- kotlin - 如何解决此错误请“Kotlin:[内部错误] java.lang.ExceptionInInitializerError”
- javascript - FetchError:无效的 json 响应正文,原因:意外的令牌 < 在 JSON 中的位置 0
- lua - 将 lua 表解包为对象并将它们映射为函数参数
- javascript - Vue:标题不会立即刷新。但是 localStorage 改变了
- python - DecisiontreeClassifier,为什么值的总和是错误的?
- velo - WIX Velo (Corvid) 的本地编辑器不加载数据库条目
- r - 如何将 strsplit 的输出转换为按列表维护 id 的数据框?
- r - R - 更改由“分配”功能创建的数据框的名称