【问题标题】:Method (with optional parameter) mocked with mockito return null on unit test. Dart Flutter用 mockito 模拟的方法(带有可选参数)在单元测试中返回 null。飞镖颤振
【发布时间】:2021-01-07 23:31:42
【问题描述】:

我花了五个小时尝试解决它,但没有任何效果。我想在从互联网加载数据后测试使用流和接收数据的 bloc 类。用例测试运行良好,但 bloc 类今天很头疼,这已经在应用程序上运行,但测试我真的不知道如何解决

文件 bloc.dart

class Bloc {
  final UseCase _useCase;
  Bloc(this._useCase);

  final _controller = StreamController.broadcast();

  Stream get stream => _controller.stream;

  doSomething() async {
    ResponseModel responseModel = await _useCase.call();
    _controller.sink.add(responseModel);//<-- I would like test this
  }

  dispose() {
    _controller.close();
  }
}

这是单元测试类 bloc_test.dart


class UseCaseMock extends Mock implements UseCase {}

main() {
  UseCase useCase;
  Bloc bloc;
  setUp(() async {
    useCase = UseCaseMock();
    bloc = Bloc(useCase);
  });

  tearDown(() {
    bloc.dispose();
  });

  group('Test Bloc', () {
    test('load stuff must sink Response ', () async {
      when(useCase.call())
          .thenAnswer((_) async => ResponseModel('id','name'));
          
       //FIRST I TRY It, DOESNT WORK   
      // await expectLater( bloc.stream, emits(isA<ResponseModel>()));


      bloc.stream.listen((response) {
      
        //print(response) <-----return null  I THINK HERE IS THE PROBLEM
        expect(response, isA<ResponseModel>());
      });

      await bloc.doSomething();
    });
  });
}

请问您知道怎么解决吗?谢谢

Solved here

【问题讨论】:

  • 您定义了一个类“MyBloc”,但在测试中您使用的是一个类“Bloc”。是不是打错字了?
  • 你从这个测试中得到了什么输出?另外,你的意思是await bloc.loadStuff()
  • @Abion47 我希望监听测试接收我通过 sink.add 发送到 bloc 中的内容。我有机会让旧代码更容易理解。
  • @Victor Eronmosele 我重写了因此是我的应用程序的伪代码。
  • 好的。我现在将发布我的答案。

标签: unit-testing flutter dart stream mockito


【解决方案1】:

解决了!我的用例有一个带有可选参数

的方法“调用”
 Future<ResponseModel> call( {String value });

我在下面嘲笑错误

 when(useCase.call()) <----------------here is the error
          .thenAnswer((_) async => ResponseModel('id','name'));

在真正的 Bloc 类中(不是我发布的伪代码)我使用参数执行一个用例

// this is the true doSomething() method on my app
loadCoupons(String storeId) async {
    final result = await searchCouponUseCase(storeId: storeId);
    _controller.sink.add(result);
  }

解决办法是: 使用可选参数模拟(如果它会被调用)!我在没有参数的情况下进行测试,因为当将“any”像 when(useCase.call(any))... 那样放入测试中时,无法编译。

 when(useCase.call(   value: ''    )) <-----solved
          .thenAnswer((_) async => ResponseModel('id','name'));

【讨论】:

    【解决方案2】:

    您可以在使用expectLater 进行断言之前运行异步操作。还要从bloc.doSomething() 中删除await,否则会超时。

    这会起作用。

    test('load stuff must sink Response ', () async {
        when(useCase.call())
            .thenAnswer((_) async => ResponseModel('id','name'));
        bloc.doSomething();
    
        await expectLater(bloc.stream, emits(isA<Response>()));
      });
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 2020-11-28
    • 2020-01-28
    • 2020-09-20
    • 2020-07-30
    相关资源
    最近更新 更多