Sometimes, there are classes that can’t be tested normally. Maybe it’s because there’s not many public methods, there’s an instance that can only run in the production code, or some other reasons. In this short article I want to share with you my experience writing tests with a powerful testing tool called Mockito.

Currently I’m working on a flutter project, and I have this ActivityItemHelper class that I want to test.

ActivityItemHelper before

the DatabaseProvider is a service to create, configure, and get the database. If the code is like that, I have no way to test insert() and queryAll() methods.

ActivityItemHelper test before

The only public methods in ActivityItemHelper are insert() and queryAll() . I can check the return output of insert() and queryAll(), but it also doesn’t work because getting the database from DatabaseProvider only works in emulator.

Then, I remember something about testing in Advanced Programming class, which is about Mockito. With Mockito, you can create an object that acts like the real service. A mock object returns a dummy data corresponding to some dummy input passed to it. But, before I can test ActivityItemHelper with Mockito, I need to change the implementation so that when I call insert(), it calls the Mock object, not the actual service. The service I’m talking about is DatabaseProvider.

To install mockito in my Flutter project, I added this to my pubspec.yaml file in dev_dependencies: .

To insert a mocked object of DatabaseProvider, we can use a technique called dependency injection.

In software engineering, dependency injection is a technique in which an object receives other objects that it depends on. These other objects are called dependencies. In the typical “using” relationship the receiving object is called a client and the passed (that is, “injected”) object is called a service.

- Wikipedia: Dependency injection

To implement dependency injection in ActivityItemHelper class, we just need to change its constructor.

ActivityItemHelper after

As you can see at line number 2 and 4, we insert dbProvider our self. So in the implementation, we use
ActivityItemHelper(dbProvider: DatabaseProvider())
but inside tests, we use
ActivityItemHelper(dbProvider: MockDatabaseProvider())

Now to we can create the test. Inside the test, I want to check if the object inserted is actually correct. For that, I use sqflite_common_ffi. It’s an sqlite3 implementation that can be used for mocking tests. This is the test for insert() that I created:

ActivityItemHelper test after

This is the insert test that I created. Here are some explanation:

  • Line 3: Initialize sqflite_common_ffi.
  • Line 6: Create a test database for testing purpose.
  • Line 7: Create the table that I can test.
  • Line 18: Create mock of MockDatabaseProvider generated from @GenerateMocks([DatabaseProvider]) .
  • Line 19: Returns future test database when DatabaseProvider.database is called . See Line 7 of ActivityItemHelper from above.
  • Line 20: Create the class to test.
  • Line 28: Insert data.
  • Line 30–41: Expect inserted data.
  • Line 42: Close and delete database so we can run other tests.

After knowing how to write a test for insert() , writing another test for queryAll() is way easier.

Personal Notes

Writing UI tests in flutter seems simple to me, but when I had to test ActivityItemHelper, I got stuck for days. The eureka moment for me was when I realized I should inject the mock object to the class I want to test. I didn’t do it sooner because I didn’t want to change the implementation of ActivityItemHelper.

Thank you for reading. I hope you find this article helpful :)

Computer Science Student

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store