I'm in the process of writing a Flutter
app with some extensive unit test coverage.
I'm using Mockito to mock my classes.
Coming from a Java
(Android
) world where I can use Mockito
to chain calls to return different values on subsequent calls.
I would expect this to work.
import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
void main() {
test("some string test", () {
StringProvider strProvider = MockStringProvider();
when(strProvider.randomStr()).thenReturn("hello");
when(strProvider.randomStr()).thenReturn("world");
expect(strProvider.randomStr(), "hello");
expect(strProvider.randomStr(), "world");
});
}
class StringProvider {
String randomStr() => "real implementation";
}
class MockStringProvider extends Mock implements StringProvider {}
However it throws:
Expected: 'hello'
Actual: 'world'
Which: is different.
The only working way I found that works is by keeping track myself.
void main() {
test("some string test", () {
StringProvider strProvider = MockStringProvider();
var invocations = 0;
when(strProvider.randomStr()).thenAnswer((_) {
var a = '';
if (invocations == 0) {
a = 'hello';
} else {
a = 'world';
}
invocations++;
return a;
});
expect(strProvider.randomStr(), "hello");
expect(strProvider.randomStr(), "world");
});
}
00:01 +1: All tests passed!
Is there a better way?
We can stub a method with multiple return values for the consecutive calls. Typical use case for this kind of stubbing could be mocking iterators.
The parameter of doReturn is Object unlike thenReturn . So, there is no type checking in the compile time. When the type is mismatched in the runtime, there would be an WrongTypeOfReturnValue execption. doReturn(true).
A typical stub is a database connection that allows you to mimic any scenario without having a real database. A mock is a fake class that can be examined after the test is finished for its interactions with the class under test. For example, you can ask it whether a method was called or how many times it was called.
The Mockito library is shipped with a BDDMockito class which introduces BDD-friendly APIs. This API allows us to take a more BDD friendly approach arranging our tests using given() and making assertions using then().
Use a list and return the answers with removeAt
:
import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
void main() {
test("some string test", () {
StringProvider strProvider = MockStringProvider();
var answers = ["hello", "world"];
when(strProvider.randomStr()).thenAnswer((_) => answers.removeAt(0));
expect(strProvider.randomStr(), "hello");
expect(strProvider.randomStr(), "world");
});
}
class StringProvider {
String randomStr() => "real implementation";
}
class MockStringProvider extends Mock implements StringProvider {}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With