Arash
Arash

Reputation: 944

After migrating flutter code to null-safety, mock objects not accepting `any`

After the release of Flutter 2, I've migrated my code to sdk: '>=2.12.0 <3.0.0' and all codes are "sound null safety" now. But I encountered errors in unit tests with mockito 5.0.0

e.g:

when(mockClient.login(any)).thenThrow(GrpcError.unavailable());

was ok earlier, but now, the compiler shows an error under any, indicating: The argument type 'Null' can't be assigned to the parameter type 'LoginRequest'

I read this link from mockito repo but I hope there is an easier way to write tests for methods with "not nullable" arguments like before.

Upvotes: 39

Views: 16787

Answers (5)

zex_rectooor
zex_rectooor

Reputation: 1002

To deal with null-safety in mockito

step 1: don't create mock classes and implementation manually so delete them

step 2: install build_runner for generating files using dart code

step 3: import 'package:mockito/annotations.dart'; to your test file

step 4: annotate your target class to be mocked with @GenerateMocks([YourClassToBeMocked]) above void main() function

step 5: run build_runner to generate mock with a --delete-conflicting-outputs flag, so in your terminal type: flutter pub run build_runner build --delete-conflicting-outputs. Enabling this option skips the prompt and deletes the files. This should typically be used in continues integration servers and tests, but not otherwise.

step6: after generating mock file import it into your test(it is located in same directory of your test file) and then you are good to go and use any in where method and also use a non-nullable variable in your classes even without implementing it.

for a full answer check out this link

Upvotes: 3

Jami
Jami

Reputation: 47

The function you are calling in the mocked class, make the argument nullable. If you are mocking this class method:

class Example {
    String method(String str) {}
}

Make the String argument nullable like:

String method(String? str) {}

Hope it works.

Upvotes: -3

Tom Crasset
Tom Crasset

Reputation: 431

When assigning the Mock object, it needs to be of the Mock object type, not the BaseClass.


@GenerateMocks(MockSpec<ITransactionRepository>(as: #MockTransactionRepository),
)
void main()
{
    ....
    ITransactionRepository baseObject = MockTransactionRepository();           // wrong
    MockTransactionRepository mockObject = MockTransactionRepository();   // right
    when(baseObject.method(any));     // results in compile error
    when(mockObject.method(any)); // OK
    ...
}

Source: https://github.com/dart-lang/mockito/issues/364

Upvotes: 33

Pablito
Pablito

Reputation: 606

See the solution here. You can use the mocktail package which makes it way easier.

With mocktail your code would become

when(() => mockClient.login(any())).thenThrow(GrpcError.unavailable());

Upvotes: 12

woprandi
woprandi

Reputation: 767

any return null and null value is not allowed to be passed to your login method.

It's the main drawback of NNBD, the mocking is much less easy than before.

https://github.com/dart-lang/mockito/blob/master/NULL_SAFETY_README.md#problems-with-typical-mocking-and-stubbing

Upvotes: 6

Related Questions