'error when Add a stub for a method using Mockito's 'when' API

Have this abstract class to get data from remote data source

abstract class NumberTriviaRemoteDataSource {
  /// Calls the http://numberapi.com/{number} endpoint.
  ///
  /// Throws a [ServerException] for all error code
  Future<NumberTriviaModel> getConcreteNumberTrivia(int number);
}

and have this abstract class for repository in domain layer

abstract class NumberTriviaRepository {
  Future<Either<Failure, NumberTrivia>> getConcreteNumberTrivia(int number);
}

bellow I created a test to implement NumberTriviaRepository class

@GenerateMocks([NumberTriviaRemoteDataSource])
void main() {
  late final NumberTriviaRepositoryImpl repository;
  late final MockNumberTriviaRemoteDataSource mockRemoteDataSource;
  setUp(() {
    mockRemoteDataSource = MockNumberTriviaRemoteDataSource();
    repository = NumberTriviaRepositoryImpl(
      numberTriviaRemoteDataSource: mockRemoteDataSource,
    );
  });
  group('getConcreteNumberTrivia', () {
    //to make test manageable create variables
    const tNumber = 1;
    const tNumberTriviaModel =
        NumberTriviaModel(text: 'test trivia', number: tNumber);
    const NumberTrivia tNumberTriviaEntity = tNumberTriviaModel;

    group('when device is online', () {
      test(
          'should return remote data when call to remote data source is successful',
          () async {
        //arrange                                
        when(mockRemoteDataSource.getConcreteNumberTrivia(any))  
            .thenAnswer((_) async => tNumberTriviaModel);               ---> Line *
        //act
        final result = await repository.getConcreteNumberTrivia(tNumber);
        //assert
        verify(mockRemoteDataSource.getConcreteNumberTrivia(tNumber));
        expect(result, equals(const Right(tNumberTriviaEntity)));
      });
    });
  });

bellow I implemented the NumberTriviaRepository class

class NumberTriviaRepositoryImpl implements NumberTriviaRepository {
  NumberTriviaRemoteDataSource numberTriviaRemoteDataSource;
  NumberTriviaRepositoryImpl(
      {required this.numberTriviaRemoteDataSource});
  @override
  Future<Either<Failure, NumberTrivia>> getConcreteNumberTrivia(
      int number) async {
    return Right(
        await numberTriviaRemoteDataSource.getConcreteNumberTrivia(number));
  }

and when run the test I get a Mock.noSuchMethod error :

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

with an explanation which is: "Add a stub for this method using Mockito's 'when' API, or generate the MockNumberTriviaRemoteDataSource mock with a MockSpec with 'returnNullOnMissingStub: true' (see https://pub.dev/documentation/mockito/latest/annotations/MockSpec-class.html)."

The problem is I created a stub method for getConcreteNumberTrivia at line * but got error and don't have any idea how to fix this. By the way, I'm learning Clean Architecture using TestDrivenDevelopment so any comment would be appriciated.



Solution 1:[1]

use setUpAll() to initiate mocks and use when in setUpAll section

@GenerateMocks([NumberTriviaRemoteDataSource])
@GenerateMocks([NumberTriviaLocalDataSource])
@GenerateMocks([NetworkInfo])
void main() {
  late final NumberTriviaRepositoryImpl repository;
  late final MockNumberTriviaRemoteDataSource mockRemoteDataSource;
  late final MockNumberTriviaLocalDataSource mockLocalDataSource;
  late final MockNetworkInfo mockNetworkInfo;

  const tNumber = 1;
  const tNumberTriviaModel =
      NumberTriviaModel(text: 'test trivia', number: tNumber);
  const NumberTrivia tNumberTriviaEntity = tNumberTriviaModel;
  setUpAll(() {
    mockRemoteDataSource = MockNumberTriviaRemoteDataSource();
    mockLocalDataSource = MockNumberTriviaLocalDataSource();
    mockNetworkInfo = MockNetworkInfo();
    repository = NumberTriviaRepositoryImpl(
      numberTriviaRemoteDataSource: mockRemoteDataSource,
      numberTriviaLocalDataSource: mockLocalDataSource,
      networkInfo: mockNetworkInfo,
    );

    when(mockRemoteDataSource.getConcreteNumberTrivia(any))
        .thenAnswer((_) async => tNumberTriviaModel);
  });
  group('getConcreteNumberTrivia', () {
    //to make test manageable create variables

    test('should check if the device is online', () {
      //arrange
      when(mockNetworkInfo.isConnected).thenAnswer((_) async => true);
      // act
      repository.getConcreteNumberTrivia(tNumber);
      // assert
      verify(mockNetworkInfo.isConnected);
    });
    group('when device is online', () {
      setUp(() {
        when(mockNetworkInfo.isConnected).thenAnswer((_) async => true);
      });
      test(
          'should return remote data when call to remote data source is successful',
          () async {
        //arrange
        when(mockRemoteDataSource.getConcreteNumberTrivia(any))
            .thenAnswer((_) async => tNumberTriviaModel);

        //act
        final result = await repository.getConcreteNumberTrivia(tNumber);
        //assert
        verify(mockRemoteDataSource.getConcreteNumberTrivia(tNumber));
        expect(result, equals(const Right(tNumberTriviaEntity)));
      });
  });
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 zex_rectooor