How to create a retrofit.Response object during Unit Testing with Retrofit 2
The retrofit.Response
class has static factory methods to create instances:
public static <T> Response<T> success(T body) {
/* ... */
}
public static <T> Response<T> success(T body, com.squareup.okhttp.Response rawResponse) {
/* ... */
}
public static <T> Response<T> error(int code, ResponseBody body) {
/* ... */
}
public static <T> Response<T> error(ResponseBody body, com.squareup.okhttp.Response rawResponse) {
/* ... */
}
For example:
Account account = ...;
retrofit.Response<Account> aResponse = retrofit.Response.success(account);
Or:
retrofit.Response<Account> aResponse = retrofit.Response.error(
403,
ResponseBody.create(
MediaType.parse("application/json"),
"{\"key\":[\"somestuff\"]}"
)
);
Note: In latest Retrofit version (2.7.1) for Kotlin, it recommends to use extension method like this:
Response.error(
400,
"{\"key\":[\"somestuff\"]}"
.toResponseBody("application/json".toMediaTypeOrNull())
)
This falls under Effective Java Item 1: Consider static factory methods instead of constructors.
A Kotlin + Mockito + okhttp3 example using Response.Builder
val mockResponse: Response<MyResponseReturnType> =
Response.success(mock<MyResponseReturnType>(),
okhttp3.Response.Builder()
.code(200)
.message("Response.success()")
.protocol(Protocol.HTTP_1_1)
.request(Request.Builder().url("http://test-url/").build())
.receivedResponseAtMillis(1619053449513)
.sentRequestAtMillis(1619053443814)
.build())
Heres how to mock just the retrofit responses
First you need to add these dependencies in build.gradle:
// mock websever for testing retrofit responses
testImplementation "com.squareup.okhttp3:mockwebserver:4.6.0"
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
Mock a successful 200 response:
val mockResponseBody = Mockito.mock(MoviesResponse::class.java)
val mockResponse = Response.success(mockResponseBody)
Mock an unsuccessful response (eg 400, 401, 404):
val errorResponse =
"{\n" +
" \"type\": \"error\",\n" +
" \"message\": \"What you were looking for isn't here.\"\n"
+ "}"
val errorResponseBody = errorResponse.toResponseBody("application/json".toMediaTypeOrNull())
val mockResponse = Response.error<String>(400, errorResponseBody)
No need to create a mock webserver and all that extra work.