Álvaro Menezes
Álvaro Menezes

Reputation: 1768

Method (with optional parameter) mocked with mockito return null on unit test. Dart Flutter

Im five hours trying solve it, doesn't work nothing. I wanna test bloc class that use stream and sink data after load data from internet. The use case test work well but the bloc class was a huge headache today, this already work on app, but the test I really dont know how to solve

file 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();
  }
}

This is the unit test class 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();
    });
  });
}

Please, would you know how to solve it? Thanks

Solved here

Upvotes: 3

Views: 4621

Answers (2)

&#193;lvaro Menezes
&#193;lvaro Menezes

Reputation: 1768

Solved! my usecase has a method "call" with an optional parameter

 Future<ResponseModel> call( {String value });

I was mocking wrong as below

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

Inside true Bloc class(not a pseudocode that I had posted) I execute a usecase using the parameter

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

And the solution is: Mock using optional parameter(if it will be called)! I was testing without parameter because when putting "any" inside the test like a when( useCase.call( any))... not compile.

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

Upvotes: 3

Victor Eronmosele
Victor Eronmosele

Reputation: 7726

You can run your async operation before using expectLater for assertion. Also remove the await from bloc.doSomething() as it times out otherwise.

This will work.

test('load stuff must sink Response ', () async {
    when(useCase.call())
        .thenAnswer((_) async => ResponseModel('id','name'));
    bloc.doSomething();

    await expectLater(bloc.stream, emits(isA<Response>()));
  });

Upvotes: 1

Related Questions