Stubbing functions not in a class

Was hoping someone would be able to explain how we can write unit tests that stub a function that isn’t in a class. For example, how can we stub bar().

Future<dynamic> foo() async {
 final val  = await bar();
 return val;
}

In some utility file we have:

Future<dynamic> Function() bar = () async {...} ;

I found Rémi’s post about the subject here where he suggests you can make a MockFunction class and then put that in the when function from Mockito. I don’t quite understand how that will know which function to replace and when I mocked this up I get an exception, the when function runs saying Null is not a subtype of type Future.

class MockFunction extends Mock {
  Future<dynamic> call();
}

final bar = MockFunction();
when(bar()).thenAnswer((_) => Future.value(null));

I think your error is a result of not consuming Mockito correctly.

Your when operation should be invoking the call method, as it is written, I’m not sure that it is valid

E.g.

when(() => bar.call()).thenAnswer((_) => Future.value(null));

In your test, replace the bar reference with your mock instance:

void main() {
  test('Test foo with mocked bar', () async {

    final mockBar = MockFunction();
    when(mockBar()).thenAnswer((_) async => 'mocked value');

    bar = mockBar;

    final result = await foo();
    expect(result, 'mocked value');
    verify(mockBar()).called(1);
  });
}

To stub bar(), you need to explicitly assign the mock to the function in your test, like bar = MockFunction();. Then use when(bar.call()) for stubbing since call is the method being mocked.

1 Like