Flutter使用blocTest测试Cubit时actual返回空数组问题排查
错误原因
- blocTest的build回调没有返回全新的Cubit实例
blocTest内部需要自行管理被测试实例的生命周期、订阅状态流,你直接传入setUp中初始化的外部cubit实例,会导致blocTest无法正常订阅状态变更,所以收不到任何emit的状态,返回空数组。 - 预期值生成时机错误
expect回调的执行时机早于act回调,你在expect中读取cubit.state.scrollValue拿到的是初始值0.0,和实际emit的scrollValue: 49不匹配,本身预期值就是错误的。 - 重复状态被自动过滤
你在act中先后调用updateCloseContainer和handleClosingContainer,两个方法最终生成的状态完全相同(isClosed都是false,scrollValue都是49),基于Equatable的状态对比逻辑,bloc会默认过滤掉和上一次完全相同的状态,不会触发第二次emit。
修正后的测试代码
void main() { group('CloseContainerCubit', () { test( 'the initial state for the CloseContainerCubit is that cubit is not closed and scrollValue is 0)', () { final cubit = CloseContainerCubit(); expect( cubit.state, CloseContainerState(isClosed: false, scrollValue: .0)); cubit.close(); }); blocTest<CloseContainerCubit, CloseContainerState>( 'the cubit should emit a CloseContainerState(isClosed: false) ' 'when cubit.updateCloseContainer(scroll) is called ' 'and scroll < SCROLL_CLOSE_VALUE', build: () => CloseContainerCubit(), // 直接返回新实例,不要引用外部变量 act: (bloc) { bloc.updateCloseContainer(SCROLL_CLOSE_VALUE - 1); bloc.handleClosingContainer(); }, expect: () => <CloseContainerState>[ // 直接写明确的预期值,不要读取实例状态 CloseContainerState(isClosed: false, scrollValue: SCROLL_CLOSE_VALUE -1) ], ); }); }
扩展说明:如果测试滚动值大于阈值的场景,比如传入
SCROLL_CLOSE_VALUE +1,那么handleClosingContainer会生成不同的状态,此时expect需要包含两个状态:expect: () => <CloseContainerState>[ CloseContainerState(isClosed: false, scrollValue: SCROLL_CLOSE_VALUE +1), CloseContainerState(isClosed: true, scrollValue: SCROLL_CLOSE_VALUE +1), ],
内容的提问来源于stack exchange,提问作者Marcel Iwanicki
相关产品推荐
相关产品推荐

