MissingStubError when add Future method in constructor dart

201 Views Asked by At

i tried to make a similar footsteps some youtube guideline (bloc) and run perfectly in production code. The bloc guideline shows to input an asynchonous function in constructor, but when i create a simple success test occurs the error MissingStubError.

Here is the UseCase for request API (mock):

abstract class UseCase {
  Future<List<String>> call();
}

The state management classes:

abstract class TestState {}

class TestStateLoading extends Equatable implements TestState {
  const TestStateLoading();

  @override
  List<Object?> get props => [];
}

class TestStateLoaded extends Equatable implements TestState {
  final List<String> tests;

  const TestStateLoaded(this.tests);

  @override
  List<Object?> get props => [tests];
}

class TestStateError extends Equatable implements TestState {
  final String error;

  const TestStateError(this.error);

  @override
  List<Object?> get props => [error];
}

Here the Presenter. I use the external library Rxdart to use reactive programming (switchMap):

class StreamTestPresenter implements TestPresenter {
  final UseCase _useCase;

  StreamTestPresenter({required UseCase usecase}) : _useCase = usecase {
    loadData();
  }

  final _controller = StreamController<List<String>>();

  Sink<List<String>> get sink => _controller.sink;

  @override
  Stream<TestState> get testStream => _controller.stream.switchMap(_tests);

  Stream<TestState> _tests(List<String> tests) async* {
    yield TestStateLoading();
    try {
      yield TestStateLoaded(tests);
    } catch (e) {
      yield TestStateError(e.toString());
    }
  }

  Future<void> loadData() async {
    final tests = await _useCase.call();
    sink.add(tests);
  }
}

And the test. In act section, i tried to use await sut.loadData(); and without it:

@GenerateMocks([UseCase])
void main() {
  late StreamTestPresenter sut;
  late MockUseCase usecase;

  setUp(() {
    usecase = MockUseCase();
    sut = StreamTestPresenter(usecase: usecase);
    when(usecase.call()).thenAnswer((_) async => ['a', 'b', 'c']);
  });
  test('Should emit correct events on UseCase success', () async {
    //arrange
    final stream = sut.testStream;
    //assert
    expectLater(
      stream,
      emitsInOrder([
        const TestStateLoading(),
        const TestStateLoaded(['a', 'b', 'c']),
      ]),
    );
    //act
  });
}

Here is the error:

MissingStubError: 'call'
No stub was found which matches the arguments of this method call:
call()

Add a stub for this method using Mockito's 'when' API, or generate the mock for MockUseCase with 'returnNullOnMissingStub: true'.
package:mockito/src/mock.dart 190:7                    Mock._noSuchMethod
package:mockito/src/mock.dart 184:45                   Mock.noSuchMethod
test\stream_test_presenter_test.mocks.dart 29:14       MockUseCase.call
package:stub_problem/stream_test_presenter.dart 33:34  StreamTestPresenter.loadData
package:stub_problem/stream_test_presenter.dart 13:5   new StreamTestPresenter
test\stream_test_presenter_test.dart 17:11             main.<fn>
===== asynchronous gap ===========================
dart:async                                             _completeOnAsyncError
package:stub_problem/stream_test_presenter.dart        StreamTestPresenter.loadData
package:stub_problem/stream_test_presenter.dart 13:5   new StreamTestPresenter
test\stream_test_presenter_test.dart 17:11             main.<fn>

Obs: When i remove the function in constructor and apply the test in act section with await sut.loadData(); works perfectly.

0

There are 0 best solutions below