-
Notifications
You must be signed in to change notification settings - Fork 164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[proposal] Alternatives for code generation with NNBD #286
Comments
The developer is free to do this. Code generation is not required when using Mockito under null safety. If the developer wishes to mock or verify methods with non-nullable parameters or return types, then code generation is one option. Manual mock implementation is another. |
The problem is that mocking manually requires a lot of boilerplate code.
What if we create alternative typed getters/methods that does not allow nullable values? We can even have it as extensions of the existing matchers. Here in the
Sample 1import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
enum LoginResult { success, invalidEmail, invalidPwd }
class MockAPIService extends Mock implements APIService {}
class APIService {
LoginResult login(String email, String pwd) {
return email.isEmpty
? LoginResult.invalidEmail
: pwd.isEmpty ? LoginResult.invalidPwd
: LoginResult.success;
}
}
void main() {
test('RegEx matcher', () {
final data = [
'[email protected]',
'[email protected]',
'[email protected]'
];
final pattern = r'(\w+)(?:@)(\w+)';
data.forEach((element) {
final r = RegExp(pattern);
r.allMatches(element).forEach((resultItem) {
final username = resultItem.group(0);
final emailDomain = resultItem.group(1);
//final emailDomain2 = resultItem.group(2);
print('$username : $emailDomain Cc: ${resultItem.groupCount}');
});
});
});
test('NNBD', () {
var server = MockAPIService();
when(server.login(anyString, '')).thenReturn(LoginResult.invalidPwd);
final result = server.login('[email protected]', '');
expect(result, LoginResult.invalidPwd);
});
}
String get anyString => any as String; Sample 2Here I just did the same one getter for integers and one function for any type
Sample 2import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
class MockHttpServer extends Mock implements HttpServer {}
class HttpServer {
Uri start(int port) {
return Uri(port: port);
}
Uri doNothing(Uri uri) {
return uri;
}
}
void main() {
test('RegEx matcher', () {
final data = [
'[email protected]',
'[email protected]',
'[email protected]'
];
final pattern = r'(\w+)(?:@)(\w+)';
data.forEach((element) {
final r = RegExp(pattern);
r.allMatches(element).forEach((resultItem) {
final username = resultItem.group(0);
final emailDomain = resultItem.group(1);
//final emailDomain2 = resultItem.group(2);
print('$username : $emailDomain Cc: ${resultItem.groupCount}');
});
});
});
test('NNBD', () {
var server = MockHttpServer();
var uri = Uri.parse('http://localhost:8080');
// server.start
when(server.start(anyInt)).thenReturn(uri);
final result1 = server.start(0000);
expect(result1.port, 8080);
// server.doNothing
when(server.doNothing(anything())).thenReturn(Uri(port: 9999));
final result2 = server.doNothing(Uri());
expect(result2.port, 9999);
});
}
int get anyInt => any as int;
T anything<T>() => any as T; @srawlins is there any problem with the suggesttions above? |
These examples result in runtime errors:
The cast ( |
Have you tried it? I have NNBD enabled and the tests pass! Edit: |
If I write this file: void main() {
String s = anyString;
}
String get anyString => null as String; into a package with this SDK constraint: environment:
sdk: '>=2.10.0 <3.0.0' and run the script with the non-nullable experiment:
then I get the following error:
|
Hm, looks live I've just enabled NNBD for the analyzer and not actually running the code with it. Just tried on Dartpad and clearly don’t work. |
This is maybe a silly question, but since |
One reason is that you cannot instantiate Never. Mockito would still need a placeholder object, a replacement for I think there are other reasons, involving how Never works. Like if Mock's noSuchMethod returned |
@srawlins |
Hmm good question. Dart's runtime-reflection library is called dart:mirrors. The question is how to preserve the current API ( You could conceive of any API where I see two problems with reflection though:
|
for anyone looking into reflection, just a heads up, so you don't waste your time: |
fwiw I’ve been messing around with an alternative mocking API to address some of these issues at https://pub.dev/packages/mocktail. |
Based on NULL_SAFETY_README.md looks like Mockito will be using code gen solution due to limitations introduced by NNBD explained in the same file. I'm creating this issue to discuss some alternative solutions since code_gen is clearly a big step back for Mockito.
Proposal
The file metioned above says that the problem is that Mockito need a default value that can be used for every parameter and with NNBD we can't use
null
because some parameters might be non-nullable. I think one option would be to make everything nullable and leave the developer make sure the API is used properly.Note: share your alternative solutions in the comments.
The text was updated successfully, but these errors were encountered: