how to test the server call with Mockito, Retrofit and RxJava

how to test the server call with Mockito, Retrofit and RxJava

In this example you can learn how to test server call with Mockito and RxJava
1. Service
2. ServiceInteractor
3. ServiceInteractorTest

Simple Service:

public interface Service {
    String URL_BASE = "https://guessthebeach.herokuapp.com/api/";

    @GET("topics/")
    Observable<List<Topics>> getTopicsRx();

}

For ServiceInteractor

public class ServiceInteractor {
    private LruCache<String, List<Topics>> cache;
    private Service service;

    public ServiceInteractor(Retrofit retrofit, LruCache<String, List<Topics>> cache) {
        this.cache = cache;
        this.service = retrofit.create(Service.class);
    }

    public Observable<List<Topics>> searchUsers() {
        return Observable.concat(cachedResults(), networkResults()).first();
    }

    private Observable<List<Topics>> cachedResults() {
        return Observable.just(cache.get("query"))
                .filter((List<Topics> result) ->
                        result != null
                );
    }

    private Observable<List<Topics>> networkResults() {
        return service.getTopicsRx()
                .doOnNext((List<Topics> result) ->
                        cache.put("query", result));
    }
}
 

The key is MockWebServer from okhttp3.

This library makes it easy to test that your app Does The Right Thing when it makes HTTP and HTTPS calls. It lets you specify which responses to return and then verify that requests were made as expected.

Because it exercises your full HTTP stack, you can be confident that you’re testing everything. You can even copy & paste HTTP responses from your real web server to create representative test cases. Or test that your code survives in awkward-to-reproduce situations like 500 errors or slow-loading responses.

Use MockWebServer the same way that you use mocking frameworks like Mockito:

  1. Script the mocks.
  2. Run application code.
  3. Verify that the expected requests were made.

Here’s a complete example in ServiceInteractorTest:

 

public class ServiceInteractorTest {
    @Mock
    private LruCache<String, List<Topics>> mCache;

    @Before
    public void setup(){

        MockitoAnnotations.initMocks(this);
        when(mCache.get(anyString())).thenReturn(null);
    }

    @Test
    public void mockServiceTest() {

        Topics topics = new Topics(1, "football");

        List<Topics> result = new ArrayList();

        result.add(topics);

        MockWebServer mockService = new MockWebServer();
        mockService.enqueue(new MockResponse().setBody(new Gson().toJson(result)));

        Retrofit retrofit = new Retrofit.Builder()
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(mockService.url("dfdf/"))
                .build();

        TestSubscriber<List<Topics>> subscriber = new TestSubscriber<>();
        ServiceInteractor serviceInteractor = new ServiceInteractor(retrofit, mCache);
        serviceInteractor.searchUsers().subscribe(subscriber);

        subscriber.assertNoErrors();
        subscriber.assertCompleted();
    }

    @Test
    public void callServiceTest() {
        Topics topics = new Topics(1, "Discern The Beach");
        Topics topicsTwo = new Topics(2, "Discern The Football Player");

        List<Topics> result = new ArrayList();
        result.add(topics);
        result.add(topicsTwo);

        MockWebServer mockWebServer = new MockWebServer();
        mockWebServer.enqueue(new MockResponse().setBody(new Gson().toJson(result)));

        Retrofit retrofit = new Retrofit.Builder()
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(mockWebServer.url("https://guessthebeach.herokuapp.com/api/"))
                .build();

        TestSubscriber<List<Topics>> subscriber = new TestSubscriber<>();
        ServiceInteractor serviceInteractor = new ServiceInteractor(retrofit, mCache);
        serviceInteractor.searchUsers().subscribe(subscriber);

        subscriber.assertNoErrors();
        subscriber.assertCompleted();
    }


}

 

You can check my example in GitHub

How to use Retrofit library

Retrofit parse JSON of your web service. Use Retrofit library is very simple

Retrofit turns your REST API into a Java interface.

you can download this example from here

You need these librarires.

JSON

Then you can get your JSON, We use this chrome app. Now you can build your model from JSON in this web

You create a new class which name is RestClient

package com.thedeveloperworldisyours.simpleretrofic.webservice;

import retrofit.Callback;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.OkClient;
import retrofit.client.Response;
import retrofit.http.GET;
import retrofit.http.Query;
import android.os.Handler;
import android.util.Log;

import com.squareup.okhttp.OkHttpClient;
import com.thedeveloperworldisyours.simpleretrofic.model.Question;
import com.thedeveloperworldisyours.simpleretrofic.utils.Constants;

public class RestClient {

	public interface ClientInterface{
		  @GET("/questions")
		  void getQuestions( @Query("sort") String sort, @Query("site") String site,@Query("pagesize") String pagesize,@Query("page") String page, Callback<Question> callback);
		}

	public static ClientInterface initRestAdapter()
    {
        OkHttpClient client = new OkHttpClient();

        return (ClientInterface) new RestAdapter.Builder()
                .setClient(new OkClient(client))
                .setEndpoint(Constants.URL)
                .build()
                .create(ClientInterface.class);
    }
	public static void GetQuestions(final Handler mHandler) {
		Callback<Question> callback = new Callback<Question>() {

			@Override
			public void failure(RetrofitError resp) {
				Log.v("failure", String.valueOf(resp.getMessage()));
			}

			@Override
			public void success(Question info, Response resp) {
				Log.v("success", String.valueOf(resp.getStatus()));
			}
		};
		RestClient.initRestAdapter().getQuestions(Constants.SORT, Constants.SITE,
				Constants.PAGESIZE, Constants.PAGE, callback);
	}

}

Now in your MainActivity put this:

package com.thedeveloperworldisyours.simpleretrofic;

import java.util.ArrayList;
import java.util.List;

import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.HeaderViewListAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Toast;

import com.thedeveloperworldisyours.simpleretrofic.model.Question;
import com.thedeveloperworldisyours.simpleretrofic.utils.Constants;
import com.thedeveloperworldisyours.simpleretrofic.utils.Utils;
import com.thedeveloperworldisyours.simpleretrofic.webservice.RestClient;

public class MainActivity extends ActionBarActivity {

	List<String> mListTitle = new ArrayList<String>();
	private ListView mListView;

		protected ListView getListView() {
		    if (mListView == null) {
		        mListView = (ListView) findViewById(android.R.id.list);
		    }
		    return mListView;
		}

		protected void setListAdapter(ListAdapter adapter) {
		    getListView().setAdapter(adapter);
		}

		protected ListAdapter getListAdapter() {
		    ListAdapter adapter = getListView().getAdapter();
		    if (adapter instanceof HeaderViewListAdapter) {
		        return ((HeaderViewListAdapter)adapter).getWrappedAdapter();
		    } else {
		        return adapter;
		    }
		}

	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.activity_main);
		getQuestionCheckInternet();

	}

	@Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.main, menu);
        return true;
    }
	@Override
    public boolean onOptionsItemSelected(MenuItem item)
    {

        switch (item.getItemId())
        {
        case R.id.action_refresh:
        	refreshList();
        	if(Utils.isOnline(MainActivity.this)){
    			Toast.makeText(this, R.string.action_refresh, Toast.LENGTH_SHORT).show();
    		}
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
        }
	public void refreshList(){
		mListTitle.clear();
		getQuestionCheckInternet();
		createList();

	}

	public void getQuestionCheckInternet(){
		if(Utils.isOnline(MainActivity.this)){
			getQuestions();
		}else{
			Toast.makeText(this, R.string.info_offline, Toast.LENGTH_LONG).show();
		}
	}

	protected void onListItemClick(ListView lv, View v, int position, long id) {
	    getListView().getOnItemClickListener().onItemClick(lv, v, position, id);
	    String item = (String) getListAdapter().getItem(position);
		Toast.makeText(this, item, Toast.LENGTH_LONG).show();
	}

	public void getQuestions() {
		Callback<Question> callback = new Callback<Question>() {

			@Override
			public void failure(RetrofitError resp) {
				Log.v("failure", String.valueOf(resp.getMessage()));
			}

			@Override
			public void success(Question info, Response resp) {
				Log.v("success", String.valueOf(resp.getStatus()));
				getTitle(info);
	            createList();
			}
		};
		RestClient.initRestAdapter().getQuestions(Constants.SORT, Constants.SITE,
				Constants.PAGESIZE, Constants.PAGE, callback);
	}

	public List<String> getTitle(Question info) {
		for (int i = 0; i < info.getItems().size(); i++) {
			mListTitle.add(info.getItems().get(i).getTitle());
		}
		return mListTitle;
	}
	public void createList(){

		// use your custom layout
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
		        android.R.layout.simple_list_item_1,mListTitle);
		setListAdapter(adapter);
	}
}

you can download this example from here