Testing with dependency retrieval
In this article I will explain how to use dependency retrieval for testing.
In the article I use code snippets from the project GPS-Texter. This application sends a text message each time distance from home location changes by 2 kilometres. In the test run I will use a mock location hardcoded in a test class, and instead of really sending text messages I will just count how many times the application was trying to send them and compare this number with the expected value.
For dependency retrieval I use Kodein.
To use Kodein in your project, add the relevant dependencies:
Contrary to the recommendation in kodein-android documentation, I do not use the Android-specific dependency implementation 'org.kodein.di:kodein-di-framework-android-x:6.0.1'
.
Creation of the module
The following snippet shows implementation of the module builder, together with the bindings that are relevant for this article:
This extention property builds the module:
The module needs to be imported in the constructor of Application
class:
Retrieval
Create one global extention function that creates instances of required types:
This will be demonstrated on the example of Bootstrap
class that is used in GPS-Texter to initialize the application once per run:
Because of the way bindings are created in the application’s Kodein module, bootstrap
is now a global property that returns a single instance of the Bootstrap
class that contains an instance of application context.
This is the way it is used for initialization of the application:
Please note that this class needs to be open
, because it needs to be overridden for testing.
Overridding of the module
This is the implementation of the overriden Kodein module:
Please note that at the top there is a definition of the property ‘mockModule’ that returns the instance of this particular class.
Mock test runner
In build.gradle
define the test runner you will be using:
Implement the test runner:
Because of this, specifically an instance of MockApplication
will be created and run.
This is the implementation of MockApplication
:
As you see, an instance of the mock Kodein module will be used. Please note the parameter allowOverride = true
.
Example mock class
This is the mock class that fails to call Android’s code for sending text messages, but just counts how many times it was called, and sets the PendingIntent
result to Activity.RESULT_OK
:
This way it can be called even on an emulator or a devide that doesn’t support texting.
The JUnit test
The test method just waits several seconds, and asserts that the number of sent messages has been at least equal to the expected value:
Because thus configured application uses the retrieved mock location simulator and mock text messages sender, the sent messages counter will be incremented so many times by the app itself, and no further steps need to be performed in the JUnit test.
Android Espresso is used herein only for waiting a specified amount of seconds. All other actions, like simulating location changes, and counting the sent messages, are performed by the retrieved objects inside of the tested application.