2012-04-27 1 views
5

Possiedo un'applicazione Web JPA/Hibernate/Spring/Tomcat con cache dati di secondo livello abilitata per motivi di prestazioni. E il cache fa il suo lavoro molto bene!Hibernate cache di dati di secondo livello e test di integrazione/accettazione

Ho anche una suite di test Cucumber che aggiunge alcuni dati di test direttamente al database dell'applicazione e quindi esegue alcuni passaggi Selenium. Certamente fallisce in quanto l'applicazione non vede gli aggiornamenti a causa della cache di secondo livello.

So che posso creare build speciali per il test con cache disabilitata (passando alcune proprietà booleane per il filtro Maven o simili) Ma ci sono molte entità annotate @Cache quindi disabilitare la cache rende l'applicazione fallire con l'eccezione "Secondo la cache di livello non è abilitata ".

Un altro approccio potrebbe essere utilizzare il servizio remoto di ehcache per svuotare la cache o configurarlo con zero object lifetime o simile.

Posso anche creare i miei dati di test utilizzando solo l'interfaccia utente dell'applicazione, ma ciò aggiunge complessità non necessaria ai casi di test, quindi preferisco scriverli sul DB prima dell'esecuzione del test.

Qualcuno potrebbe condividere il proprio approccio alle applicazioni di test di integrazione con cache di dati di secondo livello abilitata?

risposta

0

Poiché stai parlando di test funzionali tramite Selenium, dovresti considerare la tua app come una scatola nera e testarla come Selenium era in realtà un utente. Quindi è necessario passare i dati tramite l'interfaccia web e quindi verificare come l'app lo elabora e lo mostri in seguito.

L'alternativa a tali test funzionali a livello di applicazione sarà uno sviluppo basato sul comportamento con test per diversi componenti. Il componente qui è un flusso che parte dal controller e termina con DAO (solitamente DAO viene deriso in tali test che li fanno passare molto velocemente, ma non testano il funzionamento con il database). In questo caso hai un piccolo set di test per l'ambiente completo e un ampio set di test BDD.

+0

Non tutti, ma alcuni dei miei test BDD hanno i seguenti passaggi: creare dati di test, fare azioni di selenio, ripulire. D'accordo con la scatola nera, ma la creazione e la pulizia dei dati tramite l'interfaccia utente è estremamente difficile a volte e potrebbe rendere i test dipendenti l'uno dall'altro (se l'interfaccia utente relativa al salvataggio è interrotta, anche tutti gli altri test che richiedono qualcosa da salvare vengono interrotti) – ike3

+0

Sì, i test dipendenti non riusciranno, ma lo scopo principale - qualcosa non riesce, è soddisfatta. E se si inseriscono direttamente i dati in DB, allora non si tratta di test di accettazione, in sostanza, non è così che gli utenti finali lavorano con l'app. E tali test dovrebbero essere più o meno a grana grossa. Se hai bisogno di più a grana fine, questo potrebbe essere un brutto posto per il selenio. –

0

ho avuto un requisito di attuare sola lettura caching per po 'di fagioli, come paese, regione ecc ..

per controllare se sono realmente stanno ottenendo nella cache Ho scritto un test integrazione con l'utilizzo di primavera. Il test non è così appropriato, è solo una verifica di ciò che volevo ottenere. Puoi usare questo come suggerimento e implementare il tuo.

È possibile leggere here per un articolo su come scrivere un test di integrazione utilizzando la molla.

@Configurable(autowire = Autowire.BY_NAME) 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:applicationContext.xml" }) 
public class HibernateCachingTestIntg { 

    @Autowired 
    private ConfigurationDAO configurationDAO; 

    @Autowired 
    private CountryDAO countryDAO; 

    @Test 
    public void testGetCountries() { 
     for (int i = 0; i < 5; i++) { 
      StopWatch sw = new StopWatch("C"); 
      sw.start(); 
      countryDAO.listCountries(); 
      sw.stop(); 
      System.out.println(sw); 
     } 

    } 

    @Test 
    public void testGetRegionList() { 

     for (int i = 0; i < 5; i++) { 
      StopWatch sw = new StopWatch("R"); 
      sw.start(); 
      configurationDAO.getRegionList(); 
      sw.stop(); 
      System.out.println(sw); 
     } 

    } 
} 

Ed ecco l'output: -

StopWatch 'C': running time (millis) = 217; [] took 217 = 100% 
StopWatch 'C': running time (millis) = 15; [] took 15 = 100% 
StopWatch 'C': running time (millis) = 16; [] took 16 = 100% 
StopWatch 'C': running time (millis) = 15; [] took 15 = 100% 
StopWatch 'C': running time (millis) = 16; [] took 16 = 100% 

StopWatch 'R': running time (millis) = 201; [] took 201 = 100% 
StopWatch 'R': running time (millis) = 15; [] took 15 = 100% 
StopWatch 'R': running time (millis) = 0; [] took 0 = 0% 
StopWatch 'R': running time (millis) = 16; [] took 16 = 100% 
StopWatch 'R': running time (millis) = 15; [] took 15 = 100% 

Come si può vedere qui, la query richiede più tempo per eseguire per la prima volta e meno afterwords tempo. Se si attiva il logger delle query, è possibile vedere che lo SQL viene generato solo per la prima volta.

+0

Grazie. Spring-test funziona bene in quanto funziona all'interno di un singolo contesto persistente, ma i test di accettazione inseriscono i dati in un contesto separato. La mia intenzione è di testare la logica funzionale con alcune entità memorizzate nella cache in lettura e scrittura, non nella cache stessa. – ike3

0

Anche se è preferibile effettuare test di accettazione indipendenti dal DB, è necessaria una riscrittura eccessiva, quindi ho deciso di creare implementazioni molto semplici delle interfacce org.hibernate.cache.Cache e org.hibernate.cache.CacheProvider che non fanno nulla e agisce come una cache sempre vuota.

La build di test sostituisce la cache reale con questa nuova che rende felici sia le annotazioni di ibernazione che i passaggi BDD.

1

Se è necessario testare la cache di secondo livello con unit test, è necessario assicurarsi di chiudere la sessione e aprirla ogni volta che si chiama il metodo dao. Altrimenti si utilizzerà la cache di primo livello che esiste solo nell'ambito di una sessione di sospensione/corrente.