Small things when unit testing RxJava in Android
Writing always is one of my favorite, it helps me to reorganize information and save it somewhere else outside of my brain. I found it really relaxing, additionally.
A month has passed from my last post about MVP and Android new architecture. Today, I am just going to jot down a small thing about unit testings in which RxJava involves.
If you have a good habit of writing tests whenever adding new feature, you are actually confident about your clean and robust codes. If not yet, let’s build that habit from now on. It’s difficult at first (as everything else in life, no doubt), however you will see a considerably big improvement in your code structure. If you need an introduction of Android Testing, you can take a look at my previous post.
Let’s come back with the main topic. I assume that you have already worked with RxJava and MVP architectural design.
For example, we are building an Android project using MVP architecture. In general, the
presenter work is to load data from the
model and show it on the
view. Usually, when using RxJava in Android, we fetch and process data asynchronously in a specific scheduler and update or render UI behavior on the UI scheduler (main thread).
We get started with a presenter that looks like following.
Besides, another important task is to write an unit test to make sure
loadItems method run correctly as expected.
We hope to see friendly “Mr. Green”, but “Mr. Red” comes out with errors. One of the reason is that our unit test which runs on our local JVM but it triggers our codes requiring Android environment scheduler (AndroidSchedulers.mainThread()), and another scheduler (Schedulers.newThread()) that we do not have the direct control.
The solution is that we need to mock these schedulers too in addition to
model. Fortunately, in RxJava2, there is a special schedule in the purpose of testing,
Our unit test is now updated.
Obviously, we need to update the presenter too.
Besides, we are mocking
model , so there is no real interaction with real data stream, so
subscribe method will not work properly as in real environment. When unit testing, we need to call a method to trigger our test scheduler,
testScheduler.triggerActions() . Finally, our test codes look like below.
In summary, when writing tests to cover a piece of our codes which are using RxJava, just go through simple steps.
- Make sure that our codes are designed to initiate Schedulers from outside.
- Create Schedulers mock using RxJava
TestSchedulerin unit tests.
- Trigger that
TestSchedulerto drive function behavior as you expect.
It is obviously so simple as you saw. One important thing here is that after refactoring our codes to apply unit testing, its design has been improved. If we continue to cover all of our codes by tests, we definitely see the significant improvements.