Unit testing reactive network requests using RESTMock

In a real project, most android applications make network requests, and we should be testing these network requests. Initially I started with my network request testing with MockWebServer but ended up using RESTMock instead, due to its useful additional features and simplicity. I really enjoyed using, and it made a lot of my network testing easier.

The RESTMock library is a wrapper around Square’s MockWebServer. It allows you to specify Hamcrest matchers to match HTTP requests and specify what response to return.

Downloading the RESTMock library

To add the RESTMock library to our project by doing the following 2 things:

1. Add the following to your project level build.gradle allproects.repository blick:

2. Add the following to your app level build.gradle dependency block

The real code

Without any further ado lets take a look at the class will be testing, how the class is used, and then the unit test it self.

Class usage:

Simple right? I hope. Here we have a class called ProfileInformationProvider with a single function which returns us a users GitHub profile information based on the provided username. The getProfileInformationForUsername function returns an RxJava Single which we can use to subscribe to.

The Unit Test

The test rules

Before we begin testing the class, 2 test rules will need to be created.

  1. A mock web server rule which runs before every single test and terminates after every test. This rule will restart the RESTMockServer before every test, and then reset the server after the test.
  2. Since we are using reactive programming for this example (RxJava) a rule to handle asynchronous programming during unit tests. This is not handled by default.

Note: These do not have to be created as separate TestRule classes, they can just be added in the corresponding @Before or @BeforeClass functions, but for cleanliness we will create the separate test rule classes.

First lets take a look at the MockWebServerRule.

The MockWebServerRule  initializes the RESTMockServer, evaluates the test (runs the current test), and then resets RESTMockServer the after the test is complete.

Now the RxRule

This rule pretty much allows us to run asynchronous tests in our unit test. Such as network requests. This is not available by default when using RxJava so this is required.

The Actual Test

Now that we have our test rules created in our test class we need to add both of these rules:

For more detail about the difference between @Rule and @ClassRule see the following links or just command click into them in your IDE:

Next lets setup our Retrofit client and GitHubApi, and initialize our ProfileInformationProvider.

Now we can test our tests! Lets test what a successful response looks like. On a successful (200) response we expect the following to happen:

  • Receive 1 profile object for a username provided
  • No errors should occur
  • That our observer completed

Lets take a look at this together.

  • tokenMatcher: This RequestMatcher is what we use to decide what network request was made. You will see how in a sec.
  • mockResponse: This is the Mock response that we want to return when this request is made. The mock response allows us to specify parameters specific to our request such as the body, and the response code.

The next thing we do before we start testing our class is tell the mock rest server to return the mockResponse when a GET requests is made that matches the tokenMatcher. Meaning if there is a GET request that contains the path “users/” then return the mockResponse provided.

Taking a look at the rest of the test, we can see what is going on pretty clear. First we create a TestObserver of type Profile. Then we call our providers getProfileInformationForUsername function, and subscribe to it.

USER_PROFILE_MOCK_RESPONSE is just JSON representing a real success response from this network request.

Next we create a Profile object from the expected response value that will be returned.

The TestObserver assertions

Then we assert on our testObserver and make sure what we expect to happen is really happening.

  • We start by making sure we wait for any terminal event to occur.
  • Assert that there are no errors happening when the network request is made.
  • Assert that the value returned equals our mock profile object
  • Assert that only one value is returned, and finally assert that the observer is completed.

Bonus

If we wanted to test a timeout during the network request, we can use the TestScheduler available to us in the RxRule we created earlier. If you remember, we added  a timeout property to our network request which throws an error if the network requests takes 15 seconds or longer to complete.

And that’s it! It is simple as that. The RESTMock library in combination with RxJava makes unit testing reactive network requests really simple and straight forward. You can find the complete source code HERE.

Dependency injection with a library such as Dagger will make testing easier on more complex real life projects, but for simplicity it was explicitly left out.

That is all for now, if you have any questions, comments, or concerns, please do not hesitate to contact me, and remember your tests are only as good as your testing logic. I hope this post was helpful to you.

Thank you for reading.