2015-10-15 24 views
17

Durante l'utilizzo di RxJava e Retrofit 2 sto provando a creare Test di unità per coprire quando la mia app riceve risposte specifiche.Come creare un aggiornamento. Oggetto di risposta durante l'Unit Testing con Retrofit 2

Il problema che ho è che con Retrofit 2 non riesco a vedere un bel modo di creare un retrofit. Oggetto di risposta senza l'uso della riflessione.

@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); 
} 

Ho provato a utilizzare il seguente ma questo crea una risposta di OkHttp rispetto a una risposta di 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); 

risposta

34

La classe retrofit.Response ha metodi factory statici per creare istanze:

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

Per esempio:

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

O:

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

questo rientra Elemento Java efficace 1: considerare i metodi di factory statici invece dei costruttori.

+1

Questo è geniale grazie! Solo un paio di punti, come si ottiene un oggetto Risposta tipizzato (pensando che potrebbe essere utile illustrarlo per una risposta più completa) e si dispone di un collegamento all'ultima parte menzionata per un testo/articolo completo? Testerò domani AM e aggiornerò. Grazie ancora! –

+0

La memorizzazione del risultato direttamente in una variabile tipizzata (come ho fatto ora) non richiede ulteriori difficoltà. Per alcuni rari casi, potrebbe essere necessario fornire argomenti di tipo esplicito in questo modo: 'Risposta. errore (....) '. – nhaarman

+0

Java efficace è un libro di Joshua Bloch, che è prontamente disponibile. – nhaarman