2011-01-10 12 views

risposta

31

Suggerisco refactoring del codice del client per rimuovere la dipendenza diretta su RestTemplate, e sostituirlo con riferimenti a RestOperations, che è il interfaccia implementata da RestTemplate. e quello a cui dovresti scrivere.

È quindi possibile iniettare uno stub o una simulazione di RestOperations nel codice per il test dell'unità e iniettare uno RestTemplate quando lo si utilizza per davvero.

+0

Ciò che Mr @skaffman ha detto è generalmente vero e corretto.Tuttavia, devo precisare che 'RestTemplate' è usato praticamente OVUNQUE dove google ti porterà, anche' MockRestServiceServer' (come sottolineato da @Raedwald). Inoltre, Javadoc per lo stato 'RestOperations' _Non spesso utilizzato direttamente, ma un'opzione utile per migliorare la testabilità, in quanto può essere facilmente deriso o stubato._ – demaniak

+0

Una domanda successiva: se si utilizza' RestOperations' e l'istanza è consumato da un'implementazione di 'Service' (classe sotto test), come otterresti l'istanza" RestOperations' "derisa nel servizio? Istanziare il servizio direttamente nel test e utilizzare un setter? – demaniak

+1

Oggigiorno è molto facile prendere in giro un 'RestTemplate', ma è piuttosto difficile implementare tutti i metodi' RestOperations'. –

5

È possibile utilizzare le classi di simulazione nella confezione org.springframework.mock.web.

Di solito avrete bisogno di MockHttpServletRequest e MockHttpServletResponse, ma se avete bisogno di maggiore controllo potreste aver bisogno anche di altri, ad es. MockRequestDispatcher.

Entrambe implementano le interfacce Servlet corrispondenti, ma aggiungono metodi di convenienza per il test (e, soprattutto, funzionano senza una vera connessione HTTP).

si possono trovare le classi Mock nel vaso primavera-test (accessible through Maven)


Aggiornamento: sembra che le classi di cui sopra non sono di grande aiuto per RestTemplate dopo tutto. Quello di cui hai bisogno è creare un simulato ClientHttpRequestFactory, e sono sorpreso nel vedere che non ce n'è uno nel pacchetto sopra. Ecco un po 'di codice per iniziare (non hanno provato):

public class MockClientHttpRequestFactory implements 
    ClientHttpRequestFactory{ 

    // overwrite this if you want 
    protected MockClientHttpResponse createResponse(){ 
     return new MockClientHttpResponse(); 
    } 

    // or this 
    protected HttpStatus getHttpStatusCode(){ 
     return HttpStatus.OK; 
    } 

    // or even this 
    @Override 
    public ClientHttpRequest createRequest(final URI uri, 
     final HttpMethod httpMethod) throws IOException{ 
     return new MockClientHttpRequest(uri, httpMethod); 
    } 

    public class MockClientHttpResponse implements ClientHttpResponse{ 
     private final byte[] data = new byte[10000]; 
     private final InputStream body = new ByteArrayInputStream(data); 
     private final HttpHeaders headers = new HttpHeaders(); 
     private HttpStatus status; 

     @Override 
     public InputStream getBody() throws IOException{ 
      return body; 
     } 

     @Override 
     public HttpHeaders getHeaders(){ 
      return headers; 
     } 

     @Override 
     public HttpStatus getStatusCode() throws IOException{ 
      return getHttpStatusCode(); 
     } 

     @Override 
     public String getStatusText() throws IOException{ 
      return status.name(); 
     } 

     @Override 
     public void close(){ 
      try{ 
       body.close(); 
      } catch(final IOException e){ 
       throw new IllegalStateException(e); 
      } 

     } 

    } 

    class MockClientHttpRequest implements ClientHttpRequest{ 

     private final HttpHeaders headers = new HttpHeaders(); 
     private final HttpMethod method; 
     private final URI uri; 
     private final OutputStream body = new ByteArrayOutputStream(); 

     MockClientHttpRequest(final URI uri, final HttpMethod httpMethod){ 
      this.uri = uri; 
      method = httpMethod; 

     } 

     @Override 
     public OutputStream getBody() throws IOException{ 
      return body; 
     } 

     @Override 
     public HttpHeaders getHeaders(){ 
      return headers; 
     } 

     @Override 
     public HttpMethod getMethod(){ 
      return method; 
     } 

     @Override 
     public URI getURI(){ 
      return uri; 
     } 

     @Override 
     public ClientHttpResponse execute() throws IOException{ 
      return createResponse(); 
     } 

    } 


} 
+1

Non hai risposto alla mia domanda. La tua soluzione aiuta nel test del servlet lato server, framework MVC. Sto andando a testare il lato client, che usa il framework MVC. –

+0

@Dennis okay, ho aggiornato la mia risposta –

+1

Questo è proprio quello che cercavo per uno dei miei progetti REST. Grazie mille. – Elwood

3

spring-social-test contiene classi di mockup che aiutano a scrivere test per RestTemplate. Ci sono anche alcuni esempi su come usarlo all'interno del repository git (ad esempio OAuth1TemplateTest).

Si prega di tenere presente che al momento c'è una richiesta di funzionalità Spring (#SPR-7951) per spostare queste classi su spring-web.

+0

Questo è molto utile per testare i rest client. –

+1

hanno spostato questo in [spring-test-mvc] (http://tinyurl.com/csmuvdz) – mfirry

35

Sping 3.0 ha introdotto RestTemplate. Dalla versione 3.2, lo Spring MVC test framework ha fornito la classe MockRestServiceServer per il codice REST del client di test delle unità.

+0

È disponibile su Android? – Piotr

+1

@Piotr, funziona per me con gradle: androidTestCompile ("org.springframework: spring-test: 3.2.8.RELEASE") { esclude modulo: "spring-core" } – vincentjames501

Problemi correlati