Api calls in android

Testing your Api calls on Android

Jan 2, 2019 · 7 min read

Let’s start this article with a confession. I don’t test my code as much as I should. I test all my algorithms but that is pretty much all I test. I test those because it enables me to work a lot faster than if I had to build the app, install it and then visually verify (try to) that the algorithm had performed as expected. And with that approach I can quickly validate that the edge cases are properly handled without having to painfully try to replicate them on the app.

Now let’s be honest. My apps don’t have that many algorithms. What they have a lot of is Api calls. So I always thought how great it would be if I had the same level of assurance on my Api calls that I have on my algorithms. So on a new project I am working on I decided to change that and this post is what I got in result.

There are some big questions to answer when it comes to testing Api calls:

— What exactly do we test ? Which is the same as wondering what we are trying to validate.

— What tools do we need?

— How do we implement the tests?

What exactly do we test?

Let’s make something very clear: We do not test the Api. We do not send test requests to the backend to make sure it returns a response containing the expected json data. This is the responsibility of the backend developer.

We test the Api calls and the app behavior when a response is returned, no matter what the response. In other words, we test that the app sends out the proper request and properly handles the response or error. And that is already a lot.

We will not test Activities here because in my experience, instrumented testing is still too slow and we are trying to keep our testing iteration cycle as fast as possible. Therefore all our tests will be local tests. This serves a second purpose, which is to force us to separate everything that is not purely UI or Android related (fetching location, notification api…). This means no Api calls inside our Activities or Fragments which is a lot better.

Getting ready to test

This is the part where we get our hands dirty. I assume here that you are comfortable with writing basic unit test methods. Your test methods should be kept simple anyway so don’t worry they will be very easy to understand.

For this we will create an api call that performs a login operation. Here I use Retrofit. Again, if you are reading this post, I assume that performing api calls is not new to you.

This AuthenticationManager will be called by an AuthenticationInterceptor to retrieve the token or perform authentication with the hardcoded credentials.

As you can see, the Endpoint is harcoded as a constant but is also required in the constructor. This will become usefull in a second.

Mocking the Http call using MockWebServer

square/okhttp

An HTTP+HTTP/2 client for Android and Java applications. — square/okhttp

MockWebServer is a library provided by Square that lets you Mock a WebServer. The idea is that you create a mock server and you tell it what it should return when called. So you just pass it a String body and it will return it. This library also lets you inspect the calls it has received (path, params, body…). So we should have all our needs covered.

Before we can use it though, we need an efficient way to store and retrieve body responses. We don’t want to clutter our test classes with enormous json like strings. We want to save those potential responses as json files and read them for our tests.

Reading Test Resources

You start by creating a json file.

And we save it in your test resources directory exactly like this. This is important so that our test resources get picked up by the Android Gradle plugin.

Then we need a way to easy access those files.

In this class, we can access the classLoader and read the resources because we placed the resources in the “resources” directory. Otherwise we would have gotten a FileNotFoundException.

As a little bonus, and because we are into testing now ; we are going to test this MockResponseFileReader. This is really easy and will give us confidence that we are on the right track.

We create a quick test.json file that simply contains the word “success” and we test that we can successfully read it.

Using a dependency injection framework

This is clearly an optional step, but you will see that we use dependency injection by constructor in our tests so a framework can make our life easier when things become more complex or we need to refactor.

For this project, I have decided to use Koin which is very simple to use. So although it may not have all the cool features that Dagger has, it leaves you with enough brain power to understand the advantages of dependency injection while learning to use it.

InsertKoinIO/koin

KOIN — a pragmatic lightweight dependency injection framework for Kotlin — InsertKoinIO/koin

Testing Api calls

Now that we have a way to mock a server and a way to store and read mock response bodies, we are ready to write our Api tests.

Testing the request sent

I said that we should test the request sent to the server and the app behavior when handling the response, but in the case of our AuthenticationManager, testing the request sent out is basically testing that Retrofit is doing its job (which is not our responsibility). Since the AuthenticationManager is to be used with an OkHttp Interceptor, later on we will make sure that we are sending out a token in the header.

Читайте также:  Roblox ragdoll engine hack android

But for the sake of learning how to use the MockWebServer, here is a way to test that the body send is as expected.

So this is how you use the MockWebServer:

1/ Create an empty MockWebServer()

2/ Enqueue responses using the method enqueue() with a MockResponse. I don’t know if there is any limit to the number of mock responses you can enqueue.

3/ Get the base url of the server and pass it to your retrofit instance to perform the calls in your app. This is where Dependency injection is useful. Here the base Url is a dependance of the AuthenticationManager and we pass it through the constructor. Note that we could have done just the same without Koin (in fact Koin clearly gets in the way in simple cases like this one).

4/ Perform your Api call normally

5/ Check the request received by the server using server.takeRequest()

Testing the behavior on result

A very simple use case is to test that the call result correctly populates our model, whether on success or failure. It still feels a little like we are testing Retrofit, but a least we get the assurance that our model is correct.

Upon success, our AuthenticationManager should hold a Login object which contains a token or an error description.

To do those tests, we need a login_success.json and a login_failure.json files that our MockResponseFileReader can parse for us. Those mock responses are copy pasted response I obtained using Postman.

And here are the tests that use them.

If you are familiar with the junit syntax, then the only new things in this test class are the Koin related operations.

Basically, before each test we create a new instance of the AuthenticationManager using the Koin function factory. This means that a new instance of the AuthenticationManager will be created each time we call get().

A new instance of MockWebServer is also created for each test. But since we need to access the same instance multiple times during the test and at the end; we could not simply use factory. So we use the koin feature called Scope which lets us define when a particular instance should be created or dropped.

Going further

I will stop here for the code part of this tutorial because although I have written many more tests that I could share here in detail, I think there is already enough to take in for one day.

But I will still describe some use cases that I have covered in my project that I think are useful and go further than validating the model:

— Making sure the interceptor passes the token whether it is already stored or it has to perform a login first (BTW my project is an IOT device so I can’t decently ask the user to re-enter credentials if the token expires which it seems the Api is doing very often)

— In case of error on any call, make sure the api call is retried.

— In case of multiple errors, make sure the Activity gets notified (I am not testing the Activities yet).

NB: As you can see, we will test our api calls in conjunction with our Interceptors, RxJava functions and LiveDatas inside our ViewModels to make sure that they broadcast the proper information. So in an Android app, our Api call tests are more integration tests than unit tests. And that is perfectly fine =)

In conclusion, with the proper tools and goal in mind, testing the api calls in an Android app is a fairly easy task that will let us gain a lot of assurance and may very well speed up our development by allowing us to test the calls without building, installing and navigating the app.

Источник

Introduction

In this post, I will explain how to call an API using Android Studio (Android app) as well as treating its return data. I’ll be focusing mostly on the technical part (like most of the posts I’ll publish here on my blog), however, and only for personal reasons, I will contextualize this scenario and tell you why I followed this solution, but it will be just a brief summary in case you want to know this little “adventure” of mine. If you are only interested in the technical solution please click here.

In one of my school projectsВ№, my team and I decided to create an Android application for the very first time. The project was basically a meal planner app where the user can create and manipulate recipes as well as organize his/her own weekly meal plan.

I’m printing here below a few screenshots to illustrate a little about the app. When these screenshots were taken the project was still in its initial state:

One of the requirements of the project was the use of an API to fetch food items inside USDA’s database (United States Department of Agriculture). I searched in a few technology forums trying to find some practical examples, but I didn’t have much success finding a satisfactory solution which matched with the scenario of this project. So I decided to look for any documentation on the Android website (developer’s section) and I found a relatively new solution (2013) using the Volley library. This is a good solution for low payloads HTTP requests, which are usually used to populate the UI, and this was the perfect solution I was looking for.

In the following chapters, I will explain in details how to make HTTP requests using Volley. So let’s go to the solution already!

If you’d like to check the project’s source code, please follow the GitHub linkВІ

(В№) Langara College: Web and Mobile App Development — WMDD4980 Project 2

(ВІ) The available source code of the project is only a demo of the app, for obvious reasons I won’t share the whole code of the app.

Contents

1. Know The API You Are Going to Use

Firstly, it is necessary to know the API you will use. In this case, it is the USDA’s database, you can find its documentation following this link.

Usually, an API requires an access key, so you will probably need to sign up on their website and justify the use of the API, but it should be something very simple.

Читайте также:  Как включить режим настройки андроид

It’s very important to know about the API’s inputs and outputs as well, so I enforce that checking its documentation is crucial for the correct use and avoiding possible crashes.

2. Hands On (coding)

2.1. Adding Volley & Internet Permission

To use Volley’s tools, we need to add its library first. The easiest way to do that is by adding the dependency inside the file build.gradle .

Next, it’s necessary to add internet permission to your app, so add the following code between the tag manifest , inside the file AndroidManifest.xml

2.2. Creating the Queue Object

Now we need to create the object which will manage the communication between the app and the API, so we create the RequestQueue object.

For our solution, we’ll make use of the Volley.newRequestQueue .

2.3. Creating The String Request

The StringRequest object represents the data to be sent (method and URL), as well as its treatment (logic) in case of success and error of the invoked API.

2.3.1. Setting The Success and Error Returns

In the case of this project, I decided to create a separate method that returns a StringRequest object, so that way I wasn’t “polluting” the event method a lot.

2.4. Calling The API

Now that we defined the rules and procedures to the API’s return, we just need to make the call of itself. The operation is as simple as adding the StringRequest to the queue .

3. Conclusion

I found the usage of the Volley library very simple and easy to use. For a simple query like the example above, this solution performed at a good speed and it seems stable. If you need to make a simple request to retrieve light amounts of data, then this is probably a good way to call for the API you want.

You can also find some good explanations about the Volley library on YouTube here in this link.

Источник

Making Network calls on Android with Retrofit + Kotlin’s Coroutines

In recent years, the world of Android development has seen many changes. One of these changes is Kotlin’s Coroutines. Last year, the release of a stable version of Kotlin’s Coroutines saw a lot of movement from Rx Java.

In this article, we will be talking about how to combine Retrofit2 with coroutines when you are making networking calls on Android. I will be making use of News API to fetch the latest news in this example but you are free to make use of any API you want.

This article assumes that you know what Kotlin’s coroutines are. If you are not familiar with coroutines, you should through the official documentation before continuing.

I also strongly recommend this article for a better understanding of what coroutines are.

A quick recap of how Networking on android works.

Networking on android works in the following way:

First, your code makes an HTTP request to a URL or endpoint with proper headers, usually with authorization keys if required. Then, the request returns a response that will contain the content of the endpoint which is usually in JSON format. Finally, your code parses the result(JSON), gets the required value and stores them in a kotlin data class.

In this article, I will be using Okhttp for creating HTTP requests with the proper headers, Retrofit2 for making those requests and Moshi for parsing the response gotten from those requests. You are also free to use Gson for parsing the JSON response.

Let’s write some code!!

First of all, we will want to add the dependencies for all the libraries mentioned above to our project. We can go to our build.gradle file for the Module: app and add the following dependencies under the dependencies section.

You could be using any other API but if you are using news API, you will need to create an account and get an API key from the website. I would be using this key later.

After getting a valid API key from news API, you can test their endpoints and check their JSON responses. Below is an example of a JSON response from news API that gets news from Nigeria sorted by the date they were published.

You can easily convert the JSON into a Kotlin data class using the JSON to Kotlin converter plugin in Android studio. If you do not have the plugin, you can check it out here. After you have downloaded the plugin, you can right click on the package you want the data class to be located in your project, select New -> GenerateKotlinClassFile and paste your JSON in the dialogue that appears.

You will also see a settings button on the dialogue that allows you to make various configurations to your data class depending on how you want your data class to look like. Below, you will see that I have selected Moshi under annotations because I am using Moshi to parse my JSON. You can select Gson or any other library you wish to use.

Click on generate and your data classes will be ready for you to use. Below are the data classes generated from the JSON above.

You can see that the structure of the data classes corresponds to the structure of the JSON. You can also remove variables that you do not need.

Before we move on, let us take some time to review the MVVM architecture.

Here, we can see that the repository tries to get data from the data source(in this case, News API), the ViewModel checks the repository for data and the activity observes the ViewModel via what we call LiveData. Check here if you are not familiar with these concepts already. We will not be implementing the full MVVM architecture in this article since our focus here is different but We’ll be using a few concepts mentioned here in future sections of the article.

Creating the ApiClient.

The API client will help us in building this URL. These include using Okhttp to create HTTP requests, adding an interceptor that will allow us to add the API key as a query param to every request and creating our HTTP request and handler using retrofit. Let us see some code.

In the code above, you can see that we created an object and not a class because we want to call the functions and variables in the class without creating an instance of the class. The interceptor variable is going to help us add the API key as a query parameter to the URL, we then build a networking client using Okhttp and the interceptor. In the function getRetrofit(), we build the HTTP request using retrofit by adding the client we built earlier, adding the base URL of the endpoint, specifying that we are using MoshiConverter factory and also specifying the call adapter factory as the coroutineCallAdapeterFactory which is a Retrofit2 CallAdapter.Factory for Kotlin coroutine’s type Deferred .We will see why this is useful soon. You can use this interceptor for multiple HTTP requests to different URL’s, Just make sure you change the base URL for each call. The last line uses the getRetrofit() function to create our NewsApiInterface . However, we do not have an API interface yet, do we? Let’s create one!

Читайте также:  Как взломать android с android wifi

Creating the API interface.

The API interface will include functions that will make the API calls with query parameters where necessary. Note that we have made reference to this API interface in the API client which was talked about in the previous section.

In the above interface, we have created a function fetchLatestNewsAsync that is annotated with “@GET” from the retrofit2 library since we are getting data from the API. You could annotate with POST, PUT, etc depending on what endpoint you are consuming. We also added the query parameters in the URL and the path that we are going to. This will join up with the base URL so make sure that your spellings are correct. The most important thing to note about the function above is that it returns a deferred response and not just a response. When a function returns a deferred which is from the coroutine library, you can await the result of the function since the function is going to take some time to complete. If you have any other endpoints that make use of the same base URL specified in the API client, you can simply create a similar function with its own path and its own query parameters.

Time To Make the Network Calls!!

In order to make use of the classes above, we need to call them from somewhere. We could call them in our activity , fragment , repository or ViewModel . Let’s do it the right way!

First, we create a sealed class to handle network response. It can either be a success with the results coming with it or failure with an exception

We then create a base repository class to handle the safe API calls.

Here, we have two suspending higher-order functions. They both take a suspending function that returns a response(This will be the JSON response from the API) and an error message that will be displayed when an error occurs and there is no response. The newsApiOutput() function will try to get a response from the API. if it is successful, then we call the success data class in our sealed class and pass in the content of the response. If it is a failure, we call the Error data class in our sealed class and pass in an IOException with the error message. We use this newsApiOutput() function in our safeApiCall() function and return the output.

We can now create a News repository or any other repository and extend this base repository class to make a safe API call.

Our NewsRepo class extends the Base repository class so that we can call its functions and it also takes in the News API interface as a parameter. Inside a suspending function getLatestNews() that returns a mutable list of articles, we call the safeApiCall function from the base repository. This will return the latest News, we can now get the articles and convert it to a mutable list. One thing to note here is that when we were passing in the parameters for the safeApiCall() function, we had to call the function in the API Interface and await the result, This is possible because the fetchLatestNews function is returning coroutine’s Deferred type.

Creating the ViewModel and The ViewModelFactory

The ViewModel is pretty simple, we just simply create a new Job. A job is the return type of coroutine’s launch function. We can use this Job to join or cancel any coroutine at any moment. We create a coroutine context and specify the dispatcher we want our job to use. Note that there are different types of dispatchers, make sure you select the right dispatcher for your use case. Dispatchers are coroutine contexts that specify the thread or threads that can be used by the coroutine to run its code. Here I am using the default dispatcher, If you were making this call in an activity or fragment, you may want to do this using the main dispatcher in that case. Inside the coroutine scope’s launch function, we are calling the getLatestNews() function from the repository. We have to call this function inside a coroutine scope because it is a suspending function and a suspending function can only be called inside a coroutine scope or inside another suspending function. The results from this call will be posted to newsLiveData as Live Data so that it can be observed by an activity or fragment.

The View Model factory is also pretty simple. We will be using it to instantiate our view model in the activity or fragment.

Final Step. The Activity

We can now go to our activity or fragment, create an instance of the view model and use it to call getLatestNews in the view model class. we would also call newsLiveData from the view model and observe it from our fragment.

That’s it!! We have been able to easily combine Kotlin’s coroutines with the retrofit2 library to handle network calls in android! This article only treated combining coroutines with Retrofit. In a real application, you will probably want to do more than that, i.e combine it with Room, add dependency injection, etc. I have an example repository here that implements the complete MVVM architecture using coroutines. All code samples for this article can be found here. Happy Coding!

Источник

Оцените статью