Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito - stub a method after the null-safety migration

Before the null safety I could simply mock up the sendRequest(...) method like that:

 void stubBaseRepositorySendRequestResponse(String response) {
    when(baseRepository.sendRequest(onGetData: anyNamed('onGetData')))
        .thenAnswer((_) {
      return Future<String>.value(response);
    });
  }

where the signature of this method is:

Future<T> sendRequest<T>({required Future<T> Function() onGetData})

How can this be done with the new null-safe version of mockito? Can I still maintain the generic character of this stub and allow for any arguments to be passed in?

like image 578
Pablito Avatar asked Apr 27 '21 20:04

Pablito


Video Answer


2 Answers

This can be easily done with mocktail. A lot easier, without the code gen required by mockito.

Important to import mocktail first:

import 'package:mocktail/mocktail.dart';

then create a mock of the class that we want to mock:

class MockBaseRepository extends Mock implements BaseRepository {}

void stubBaseRepositorySendRequestResponse(String response) {
when(() => baseRepository.sendRequest(
        onGetData: any(named: 'onGetData', that: isNotNull))).thenAnswer((_) {
      return Future<String>.value(response);
    });
  }
like image 77
Pablito Avatar answered Oct 18 '22 03:10

Pablito


Updating stubs after mockito null-safety upgrade:

To outline the process, a stubbed class will need to be generated, which is done using build_runner package. You will need to import that class and stub required methods.

  1. Update the class - remove 'Mock' from the stub definition, because the imported stub class will start with 'Mock', eg:

class MyClass extends Mock implements MyClassBase {}

instead of


class MockMyClass extends Mock implements MyClassBase {}
  1. Before main add @GenerateMocks([MockedClass]) eg @GenerateMocks([MyClass]) (it'll require an import: import 'package:mockito/annotations.dart';)
  2. Install build_runner
  3. Generate stub class by running

flutter pub run build_runner build --delete-conflicting-outputs

  1. Import the stubbed class in your test file, which will be generated in the same directory as your test file, import will look like import '{TEST_FILE_NAME}.mocks.dart';. Now the stub class is available with the same name as given in Generate( starting with Mock, eg MockMyClass
  2. Stub required method, before the call/assertion (provide parameters and return value):
    when(mockMyClass.someFancyMethod(any, any))
        .thenAnswer((_) => Future.value(null));

PS

Was having issues mocking NavigatorObserver this way, the error I got:

The following MissingStubError was thrown building IconTheme(color: Color(0xdd000000)): 'navigator'

Stubbing navigator with NavigatorState didn't help, I guess it's related to context propagation.

I worked around it by using the following non-null safe way, as specified in mockito's null-safety guideline:

@GenerateMocks([], 
  customMocks: [
    MockSpec<NavigatorObserver>(returnNullOnMissingStub: true)
  ])

after that run

flutter pub run  build_runner build --delete-conflicting-outputs

It'll yield MockNavigatorObserver available through the import of *.mocks.dart file (mentioned above). Of course, since it's generated by mockito need to remove any custom definitions of that class.

like image 24
ego Avatar answered Oct 18 '22 05:10

ego