package com.truckmuncher.app.data;
import android.support.annotation.NonNull;
import com.truckmuncher.api.exceptions.Error;
import com.truckmuncher.api.menu.FullMenusResponse;
import com.truckmuncher.app.R;
import com.truckmuncher.testlib.ReadableRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import java.io.IOException;
import java.util.Collections;
import java.util.concurrent.Executor;
import retrofit.RestAdapter;
import retrofit.RetrofitError;
import retrofit.client.Client;
import retrofit.client.Header;
import retrofit.client.Request;
import retrofit.client.Response;
import retrofit.converter.WireConverter;
import retrofit.http.POST;
import retrofit.mime.TypedByteArray;
import retrofit.mime.TypedInput;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
@RunWith(ReadableRobolectricTestRunner.class)
public class ApiErrorHandlerTest {
ApiErrorHandler errorHandler;
@Before
public void setUp() {
errorHandler = new ApiErrorHandler(Robolectric.application);
}
@Test
public void networkError() {
RetrofitError error = RetrofitError.networkError("http://api.truckmuncher.com/com.truckmuncher.api.menu.MenuService/getFullMenus", new IOException("Failure message"));
ApiException exception = errorHandler.handleError(error);
assertThat(exception).isNotNull();
assertThat(exception.getMessage()).isEqualTo(Robolectric.application.getString(R.string.error_network));
assertThat(exception.getCause()).isEqualTo(error);
}
@Test
public void errorWithEmptyBodyDoesNotCrash() {
TestClient client = new RestAdapter.Builder()
.setEndpoint("http://example.com")
.setClient(new Client() {
@Override
public Response execute(Request request) throws IOException {
return new Response("", 400, "invalid request", Collections.<Header>emptyList(), null);
}
})
.setErrorHandler(errorHandler)
.setExecutors(new SynchronousExecutor(), new SynchronousExecutor())
.build()
.create(TestClient.class);
try {
client.getFullMenus();
failBecauseExceptionWasNotThrown(ApiException.class);
} catch (ApiException e) {
assertThat(e.getMessage()).isNull();
assertThat(e.getCause()).isNotNull();
}
}
@Test
public void ErrorWithBodyHasMessageAndCause() {
final String userMessage = "Test user message";
TestClient client = new RestAdapter.Builder()
.setEndpoint("http://example.com")
.setClient(new Client() {
@Override
public Response execute(Request request) throws IOException {
Error apiError = new Error("1234", userMessage);
TypedInput input = new TypedByteArray("application/x-protobuf", apiError.toByteArray());
return new Response("", 400, "invalid request", Collections.<Header>emptyList(), input);
}
})
.setErrorHandler(errorHandler)
.setExecutors(new SynchronousExecutor(), new SynchronousExecutor())
.setConverter(new WireConverter())
.build()
.create(TestClient.class);
try {
client.getFullMenus();
failBecauseExceptionWasNotThrown(ApiException.class);
} catch (ApiException e) {
assertThat(e.getMessage()).isEqualTo(userMessage);
assertThat(e.getCause()).isNotNull();
}
}
@Test
public void UnauthorizedOnNonAuthRouteThrowsCorrectException() {
TestClient client = new RestAdapter.Builder()
.setEndpoint("http://example.com")
.setClient(new Client() {
@Override
public Response execute(Request request) throws IOException {
Error apiError = new Error("1234", "Invalid social credentials");
TypedInput input = new TypedByteArray("application/x-protobuf", apiError.toByteArray());
return new Response("", 401, "invalid request", Collections.<Header>emptyList(), input);
}
})
.setErrorHandler(errorHandler)
.setExecutors(new SynchronousExecutor(), new SynchronousExecutor())
.setConverter(new WireConverter())
.build()
.create(TestClient.class);
try {
client.getFullMenus();
failBecauseExceptionWasNotThrown(ExpiredSessionException.class);
} catch (ExpiredSessionException e) {
// No-op
}
}
interface TestClient {
@POST("/")
FullMenusResponse getFullMenus();
}
static class SynchronousExecutor implements Executor {
@Override
public void execute(@NonNull Runnable command) {
command.run();
}
}
}