Override/mock library functions for dart/flutter testing
Things like mockito
work by creating mock classes that implement the interface of the mocked class. That doesn't work for global and static functions, however.
What you instead can do is to avoid calling those global/static functions directly and instead call them through an extra level of indirection. For example:
import 'package:foo_package/exposing_foo_function.dart' as foo_package;
class TestableClass {
final bool Function() foo;
TestableClass({this.foo = foo_package.foo});
bool bar() {
return foo();
}
}
and then to test:
void main() {
test('TestableClass.bar() when foo_package.foo() returns false', () {
bool fakeFoo() => false;
TestableClass testableClass = TestableClass(foo: fakeFoo);
expect(testableClass.bar(), isFalse);
});
}
A similar approach is to wrap the global/static functions as instance methods of a class:
import 'package:foo_package/exposing_foo_function.dart' as foo_package;
class FooManager {
bool foo() => foo_package.foo();
}
var fooManager = FooManager();
class TestableClass {
bool bar() {
return fooManager.foo();
}
}
and then your tests can mock FooManager
like any other class and set fooManager
to the mocked version. (Or if you prefer dependency inversion to global variables, passing your mocked version of FooManager
to TestableClass
as a construction argument.)
Of course, all of the above will help only for your own calls that go through your wrappers. It won't help if code you don't control calls those functions. In that case, your best course of action might be to complain to the function's author about lack of testability.
Roboroads
I am Robbin and I am a very enthusiastic programmer. It doesn't matter what I may program, even if it's washingmachines, apps, software for PC, websites, you name it, I am driven by the appreciation earned for when something works and it feels good to see that the things I made are being used. No programming language is too comprehensive for me. Finally, I am a man of humor, I am (or try to be) very social, I can explain thing on basic levels (or metaphorically) and above all I am someone who one can get along with.
Updated on January 01, 2023Comments
-
Roboroads over 1 year
I was wondering if there is a way to override library functions so they don't fire or just return something else.
import 'package:foo_package/exposing_foo_function.dart'; class TestableClass { bool bar() { return foo(); //foo is from the imported library } }
Test:
void main() { test('TestableClass.bar() when foo_package.foo() returns false', () { TestableClass testableClass = TestableClass(); // Something to make foo_package.foo() return false. expect(testableClass.bar(), isFalse); }); }
-
Roboroads over 2 yearsThis is exactly what i have been doing, which works okay. I was wondering if there is another way of going about it.