如何进行改造.在单元测试与改造2中的响应对象



在使用RxJava和Retrofit 2时,我试图创建单元测试来覆盖我的应用程序何时收到特定的响应。

我的问题是,在《Retrofit 2》中,我看不到一个创造改造的好方法。

@Test
public void testLogin_throwsLoginBadRequestExceptionWhen403Error() {

    Request.Builder requestBuilder = new Request.Builder();
    requestBuilder.get();
    requestBuilder.url("http://localhost");
    Response.Builder responseBuilder = new Response.Builder();
    responseBuilder.code(403);
    responseBuilder.protocol(Protocol.HTTP_1_1);
    responseBuilder.body(ResponseBody.create(MediaType.parse("application/json"), "{"key":["somestuff"]}"));
    responseBuilder.request(requestBuilder.build());
    retrofit.Response<LoginResponse> aResponse = null;
    try {
        Constructor<retrofit.Response> constructor= (Constructor<retrofit.Response>) retrofit.Response.class.getDeclaredConstructors()[0];
        constructor.setAccessible(true);
        aResponse = constructor.newInstance(responseBuilder.build(), null, null);
    } catch (Exception ex) {
        //reflection error
    }
    doReturn(Observable.just(aResponse)).when(mockLoginAPI).login(anyObject());
    TestSubscriber testSubscriber = new TestSubscriber();
    loginAPIService.login(loginRequest).subscribe(testSubscriber);
    Throwable resultError = (Throwable) testSubscriber.getOnErrorEvents().get(0);
    assertTrue(resultError instanceof LoginBadRequestException);
}

我已经尝试使用以下内容,但这会创建一个OkHttp响应与一个Retrofit响应。

    Request.Builder requestBuilder = new Request.Builder();
    requestBuilder.get();
    requestBuilder.url("http://localhost");
    Response.Builder responseBuilder = new Response.Builder();
    responseBuilder.code(403);
    responseBuilder.protocol(Protocol.HTTP_1_1);

retrofit.Response类有静态工厂方法来创建实例:

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) {
  /* ... */
}
例如:

Account account = ...;
retrofit.Response<Account> aResponse = retrofit.Response.success(account);

或:

retrofit.Response<Account> aResponse = retrofit.Response.error(
  403, 
  ResponseBody.create(
    MediaType.parse("application/json"),
    "{"key":["somestuff"]}"
  )
);

注意:在Kotlin的最新Retrofit版本(2.7.1)中,它建议使用这样的扩展方法:

Response.error(
  400,
  "{"key":["somestuff"]}"
    .toResponseBody("application/json".toMediaTypeOrNull())
)

这属于Effective Java Item 1:考虑静态工厂方法而不是构造函数

下面是如何模拟改装响应

首先你需要在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"

模拟成功的200响应:

val mockResponseBody = Mockito.mock(MoviesResponse::class.java)
val mockResponse = Response.success(mockResponseBody) 

模拟不成功的响应(例如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)

不需要创建一个模拟web服务器和所有额外的工作。

使用响应的Kotlin + Mockito + okhttp3示例。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())

不是在字符串上使用toResponseBody()扩展函数,而是在字节数组上使用它,如下所示。

Response.error(400, byteArrayOf().toResponseBody())

byteArrayOf().toResponseBody()会创建一个ResponseBody

相关内容

  • 没有找到相关文章

最新更新