如何使用 blocTest 对 bloc 进行单元测试?

Posted

技术标签:

【中文标题】如何使用 blocTest 对 bloc 进行单元测试?【英文标题】:How to do Unit Testing on bloc using blocTest? 【发布时间】:2021-11-30 03:38:29 【问题描述】:

我有一个 bloc 可以通过 id 从 orderItem 获取 cartItem,我想测试这个 bloc,我已经阅读了一些来自 flutter_bloc 的 bloc 测试,但我仍然不知道如何在我的 bloc 上实现它。我想使用我制作的虚拟数据进行测试。我希望它在发出 CartItemCheck 事件时获取虚拟列表,并在发出 CartItemUncheck 时删除列表。这是我的集团代码:

import...

abstract class CartItemEvent 
  const CartItemEvent();


class CartItemCheck extends CartItemEvent 
  final CartItem? item;

  CartItemCheck(this.item);

  List<Object> get props => [item!];

  @override
  String toString() => 'CartItemChecked  item: $item ';


class CartItemUncheck extends CartItemEvent 
  final CartItem? item;
  CartItemUncheck(this.item);

  List<Object> get props => [item!];

  @override
  String toString() => 'CartItemUnchecked  item: $item ';


class CartItemUpdate extends CartItemEvent 
  final String? itemId;
  final String? type;

  CartItemUpdate(this.itemId, this.type);

  List<Object> get props => [itemId!, type!];

  @override
  String toString() => 'CartItemUpdated  item: $itemId ';



class CartItemBloc extends Bloc<CartItemEvent, List<CartItem>> 
  final List<CartItem>? initialItems;

  CartItemBloc(this.initialItems) : super(initialItems!);

  @override
  Stream<List<CartItem>> mapEventToState(CartItemEvent event) async* 
    if (event is CartItemCheck) 
      List<CartItem> newItems = state..add(event.item!);
      yield newItems.toList();
    
    else if (event is CartItemUncheck) 
      List<CartItem> newItems = state.where((item) => item.itemId != event.item!.itemId).toList();
      yield newItems.toList();
     else if (event is CartItemUpdate) 
      CartItem oldItem = state.where((item) => item.itemId == event.itemId).first;
      List<CartItem> cartItems = state;
      if (event.type == 'increment') 
        CartItem updatedItem = oldItem.copyWith(qty: oldItem.qty + 1);
        cartItems[cartItems.indexWhere((item) => item.itemId == event.itemId)] = updatedItem;
        yield cartItems.toList();
       else 
        CartItem updatedItem = oldItem.copyWith(qty: oldItem.qty - 1);
        cartItems[cartItems.indexWhere((item) => item.itemId == event.itemId)] = updatedItem;
        yield cartItems.toList();
      
    
  

这是我当前的测试代码:

import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pikpo_screen/blocs/cart_item_bloc.dart';
import 'package:pikpo_screen/model/cart_item.dart';
import 'package:pikpo_screen/util/order_helper.dart';

main()
  CartItemBloc? cartItemBloc;
  List<CartItem> expectedResult = [CartItem(itemId: "1"), CartItem(price: 35), CartItem(qty: 2)];
  List<CartItem> initialItem = [];
  setUp(() 
    cartItemBloc = CartItemBloc(initialItem);
  );

  test('initial state is []', () 
    expect(cartItemBloc!.state, []);
  );
  blocTest('description',
      build: () => cartItemBloc,
    act: (bloc) => bloc.add(CartItemCheck()),
    expect: () => [1]
  );

提前感谢您帮助我

【问题讨论】:

【参考方案1】:

在您的 bloc 中,您发出一个 CardItem 列表,并且 bloc 测试需要一个状态列表。因此,您在 expect 函数的列表中有一个列表。

void main() 
  late CartItemBloc cartItemBloc;

  const expectedResult = [
    CartItem(itemId: '1'),
    CartItem(price: 35),
    CartItem(qty: 2)
  ];

  final initialItem = <CartItem>[];

  setUp(() 
    cartItemBloc = CartItemBloc(initialItem);
  );

  blocTest<CartItemBloc, List<CartItem>>(
    'description',
    build: () => cartItemBloc,
    act: (bloc) => bloc.add(const CartItemCheck(item: CartItem())),
    expect: () => [
      [
        const CartItem(),
      ]
    ],
  );

【讨论】:

以上是关于如何使用 blocTest 对 bloc 进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

使用具有列表类型参数的 dart 类,如何使其具有等价性

Flutter bloc emmitInOrder 不会发出初始状态,但会发出

Flutter - 使用国际翻译对 Cubit/ Bloc 内的消息进行应用本地化

Flutter BLoC 测试

如何在颤动中使用 bloc 模式进行错误处理?

Flutter BLoC 模式 - 如何在流事件后导航到另一个屏幕?