16

Here i got a sample of code in presenter. How do i make write a test for onSuccess and onFailure in retrofit call

public void getNotifications(final List<HashMap<String,Object>> notifications){ if (!"".equalsIgnoreCase(userDB.getValueFromSqlite("email",1))) { UserNotifications userNotifications = new UserNotifications(userDB.getValueFromSqlite("email",1),Integer.parseInt(userDB.getValueFromSqlite("userId",1).trim())); Call call = apiInterface.getNotifications(userNotifications); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { UserNotifications userNotifications1 = (UserNotifications) response.body(); if(userNotifications1.getNotifications().isEmpty()){ view.setListToAdapter(notifications); onFailure(call,new Throwable()); } else { for (UserNotifications.Datum datum:userNotifications1.getNotifications()) { HashMap<String,Object> singleNotification= new HashMap<>(); singleNotification.put("notification",datum.getNotification()); singleNotification.put("date",datum.getDate()); notifications.add(singleNotification); } view.setListToAdapter(notifications); } } @Override public void onFailure(Call call, Throwable t) { call.cancel(); } }); } } } 

How do i write unittesting to cover all cases for this piece of code.

Thanks

2 Answers 2

34
+50

When you want to test different responses from service (API) it's probably best to mock it and return what you need.

 @Test public void testApiResponse() { ApiInterface mockedApiInterface = Mockito.mock(ApiInterface.class); Call<UserNotifications> mockedCall = Mockito.mock(Call.class); Mockito.when(mockedApiInterface.getNotifications()).thenReturn(mockedCall); Mockito.doAnswer(new Answer() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Callback<UserNotifications> callback = invocation.getArgumentAt(0, Callback.class); callback.onResponse(mockedCall, Response.success(new UserNotifications())); // or callback.onResponse(mockedCall, Response.error(404. ...); // or callback.onFailure(mockedCall, new IOException()); return null; } }).when(mockedCall).enqueue(any(Callback.class)); // inject mocked ApiInterface to your presenter // and then mock view and verify calls (and eventually use ArgumentCaptor to access call parameters) } 
Sign up to request clarification or add additional context in comments.

14 Comments

Thankyou soo much dude... it really saved my day
could you please explain me about Mockito.doAnswer(something..)
You use that notation to specify mock behavior. It's similar to Mockito.when(mockObject).someMethod(any(Parameter.class)).thenReturn(returnValue); but this one must be used for functions with no (void) return type. See testing.googleblog.com/2014/03/….
This works well, however there is race condition that will cause tests to fail. Once enqueue is called, the unit test will continue and try to verify things that haven't been called yet. Is there a way to get the callback to finish first?
@ShrimpCrackers Are you sure you're injecting the mocked ApiInterface to your production code? Because the code introduced above only specifies the behavior of the mock, it doesn't actually execute anything.
|
1

For those looking for an answer using Kotlin and MockK:

Assume you have something like this:

class ApiService(private val client: OkHttpClient) { fun makeApiCall() { val url = "https://someendpoint.com.br/" val request = Request.Builder().url(url).build() client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, exception: IOException) { //Logic to handle Failure } override fun onResponse(call: Call, response: Response) { //Logic to handle Success } }) } } 

You can test this using Junit 5 and mockK

class ApiServiceTest { private lateinit var client: okhttp3.OkHttpClient private lateinit var apiService: ApiService @BeforeEach fun setup() { // Setup a new mock for each test case client = mockk(relaxed = true) apiService = ApiService(client) } @Test fun `test with mockedCallback`() { val mockedCall = mockk<Call>(relaxed = true) every { mockedCall.enqueue(any()) } answers { //Get the callback from the arguments val callback = args[0] as Callback // Create a fakeRequest val fakeRequest = okhttp3.Request.Builder().url("https://someendpoint.com.br/").build() // Create the response you need to test, it can be failure or success val errorResponse = Response.Builder() .request(fakeRequest) .protocol(Protocol.HTTP_1_1) .code(400) .message("Error") .build() //Call the callback with the mocked response you created. callback.onResponse(mockedCall, errorResponse) } // Setup the client mock to return the mocked call you created every { client.newCall(any()) } returns mockedCall apiService.makeApiCall() // Verify whatever you need to test your logic to handle each case. } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.