2016-03-21 23 views
6

Usiamo MockMvc Framework per testare i Spring Controller con JUnit. Il controller restituisce DefferedResult.Test di integrazione MockMvc Spring Up Spring con Embedded Cassandra

Il mockmvc.perform sembra muggito

mockMvc.perform(post("/customer") 
       .accept(APPLICATION_JSON) 
       .header(AUTH_TOKEN_KEY, "xyz") 
       .header(FROM_KEY, "[email protected]") 
       .content(json) 
       .contentType(APPLICATION_JSON)) 
       .andExpect(status().isOk()) 
       .andExpect(request().asyncStarted()); 

e ci vuole un sacco di tempo. Utilizziamo la cassandra incorporata e per questo ci vuole molto tempo.

Ho provato anche questo, ma è lo stesso.

MvcResult mvcResult = mockMvc.perform(post("/customer") 
      .accept(APPLICATION_JSON) 
      .header(AUTH_TOKEN_KEY, "xyz") 
      .header(FROM_KEY, "[email protected]") 
      .content(json) 
      .contentType(APPLICATION_JSON)) 
      .andReturn(); 

mockMvc.perform(asyncDispatch(mvcResult)) 
      .andExpect(status().isOk()) 
      .andExpect(request().asyncStarted()); 

Ho centinaia di test, per cui il processo di compilazione è molto lento.

C'è un modo, utilizzando JUnit posso dire eseguire la richiesta e attendere la risposta in un altro thread per affermare i risultati, o comunque un buon modo per accelerarlo.

Grazie

+0

Penso che il modo migliore per ottenere una risposta sia creare uno snippet completo end-to-end, ad es. ospitato su una pagina GitHub da qualche parte in modo che le persone possano giocare con un gioco e vedere le statistiche sul rendimento. A causa della natura di questo (test di integrazione) dubito che otterrete una risposta accurata e utile senza fornire del codice. – bobmarksie

risposta

1

Come ho detto nella mia domanda Stiamo usando cassandra incorporata e per questo ci vuole un sacco di tempo.

Ho provato a cercare le cose nel file cassandra.yaml e ho modificato la riga di seguito.

commitlog_sync_batch_window_in_ms: 90 

a

commitlog_sync_batch_window_in_ms: 1 

Questo è tutto e il tempo di costruzione è stato ridotto da 30 minuti a 2 minuti.

Dai commenti cassandra.yaml: -

Si attenderà fino a commitlog_sync_batch_window_in_ms millisecondi per altre operazioni di scrittura, prima di eseguire la sincronizzazione.

Dopo aver ridotto questo tempo, il tempo di attesa è stato ridotto e il tempo di costruzione è stato ridotto.

0

Stai facendo quanto segue?

  1. Esecuzione come "Test di integrazione molla"? per esempio.

    @RunWith(SpringJUnit4ClassRunner.class) 
    @ContextConfiguration(classes = CassandraConfig.class) 
    public class BookRepositoryIntegrationTest { 
        // 
    } 
    
  2. State avviare e arrestare il server di Casandra incorporato utilizzando l'@BeforeClass/@ AfterClass` annotazioni? per esempio.

    @BeforeClass 
    public static void startCassandraEmbedded() { 
        EmbeddedCassandraServerHelper.startEmbeddedCassandra(); 
        Cluster cluster = Cluster.builder() 
         .addContactPoints("127.0.0.1").withPort(9142).build(); 
        Session session = cluster.connect(); 
    } 
    
    ... and ... 
    
    @AfterClass 
    public static void stopCassandraEmbedded() { 
        EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); 
    } 
    

Vedi http://www.baeldung.com/spring-data-cassandra-tutorial per ulteriori informazioni

+0

sì, stiamo eseguendo 'Spring Integration Test' e non stiamo * avviando e fermando * cassandra prima di ogni classe, perché penso che l'avvio del server Cassandra e le migrazioni in esecuzione aumenteranno il tempo. – Mritunjay

+0

OK bene, hai identificato dove è la lentezza? È forse 'DeferredResult'? È gestito attualmente su un altro thread? – bobmarksie

+0

no, in realtà eseguiamo tutto il lavoro e quindi otteniamo il risultato, lo racchiudiamo in "DeferredResult" e lo restituiamo dal metodo. – Mritunjay

0

Avete veramente bisogno la Cassandra/Persistenza strati della vostra applicazione per questo test?

Se l'anser è no, o se la risposta non è una vasta gamma di casi di test, allora è possibile iniettare un altro repository di persistenza durante l'esecuzione dei test. Per raggiungere questo obiettivo, si potrebbe usare Primavera costruita nel Profile funzionalità e annotare i test di conseguenza, ad esempio:

@RunWith(SpringJUnit4ClassRunner.class) 
@ActiveProfile("StubPersistence") 
public class WebLayerIntegrationTests { 
... 
} 

È quindi possibile avere una versione spense del vostro Cassanda-repository per i test, che sono autorizzati a lavorare con dati statici:

@Profiles("StubPersistence") 
@Repository 
public class StubCassandaRepository { 
    ... 
} 

Questa classe potrebbe essere sostenuta da una semplice struttura di dati come un HashSet o simili, depdends sul vostro caso d'uso. La possibilità di questo approccio dipende dall'architettura del software, quindi potrebbe non essere possibile se non riesci a eliminare le dipendenze di Cassandra.

Mi chiedo anche se è davvero necessario eseguire centinaia di test, che richiedono l'applicazione completa, incluso il livello Web. Ovviamente è possibile accelerare significativamente i test favorendo i Test di unità sui test di integrazione, in modo da non dover avviare il contesto di primavera. Dipende anche dalla tua applicazione e dall'architettura del software.

Ci saranno anche alcuni miglioramenti di prova in Primavera-Boot 1.4 che vi permetterà di initilize specificamente singole fette della vostra applicazione per il test (come persistenza, o Web-Layer): https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4

Quindi, il mio migliore consiglio è: Se vuoi testare i tuoi Controllori, prova solo i tuoi Controller e non il tuo Livello di Persistenza, stub invece. Se vuoi testare il tuo Persistence-Layer, inizia con le interfacce del tuo Persistence-Layer, non usare i Controller come interfaccia di test.