2012-04-12 20 views
30

Come si possono prendere in giro le numerose dipendenze necessarie per i test di integrazione?Mocking per test di integrazione

io uso Mockito per il mio test di unità 'puri'. "Puro" in questo caso significa testare una singola classe, prendendo in giro tutte le sue dipendenze. Bellissimo.

Ora vengono i test di integrazione. Diciamo che in questo caso un test di integrazione metterà alla prova qualcosa di simile:

  1. messaggio viene inserito in una coda
  2. messaggio è 'trasformato'
  3. messaggio di risposta viene messo in una coda di risposta

Diciamo anche che l'elaborazione che avviene nel passaggio 2 è roba seria. Si basa su molte interazioni tra database, su più servizi esterni, sul file system, su tutti i tipi di cose. Ci sono anche molti effetti collaterali che il flusso si innesca, quindi non posso semplicemente assicurare che la risposta sia corretta - ho bisogno di verificare gli effetti collaterali.

Ciascuna di queste dipendenze sono avvolti da una sola classe di servizio senza stato, che li rende bello e mockable.

Come sono persone la manipolazione di questo?

mi piacerebbe utilizzare Mockito modo che ho potuto verificare gli effetti collaterali che il suddetto flusso avrà. Tuttavia, la documentazione di Mocktio (e in larga misura la sua implementazione) sembra combattere fortemente contro l'utilizzo in contesti diversi dai test unitari "puri". Ho cercato di seguire questa strada, ma

  • è difficile per popolare i dati stub (come c'è un sacco di esso)
  • E 'difficile avere Primavera iniettare quei casi sradicate nei miei fagioli
  • è difficile per "resettare" i gesti in modo da poter verificare un diverso insieme di interazioni senza cancellare gli stub.

EDIT

So che avrei potuto gestire la questione del database con qualcosa come un'istanza HSQLDB, ma c'è ancora la questione dei servizi esterni. Per la ripetibilità non posso fare affidamento su questi servizi, essendo nello stato che richiedo, ecc. L'unica opzione che vedo è di prenderli in giro.

Whatdaya fare?

+1

Giusto per chiarire, in quanto i test di integrazione possono essere eseguiti in due modi. Sembra che tu intenda test di integrazione, testando che i componenti di connessione funzionino bene insieme (essenzialmente testando le API). Ma a volte l'integrazione si riferisce a end-to-end, quindi non prenderebbe in giro il tuo servizio e in realtà permetteresti di colpire il database. Questo chiarimento può aiutare con la risposta ... Per favore, vedi http://stackoverflow.com/questions/4904096/whats-the-difference-between-unit-functional-acceptance-and-integration-test per ulteriori chiarimenti sui tipi –

+0

si applica davvero a qualsiasi test (integrazione o end-to-end) che richiede molte dipendenze esterne. Ad esempio, potrei sostituire i miei stub di database con un'istanza HSQLDB, ma ho ancora tutti gli altri servizi. Modificherà la domanda un po 'per chiarire .. –

+0

Quindi, come hai risolto il problema beffardo? – Pupsik

risposta

7

Ottima domanda.

Sembra che tu abbia raggiunto i limiti di Mockito. Mockito è ottimo se vuoi controllare le interazioni tra oggetti.

Ciò che si desidera, tuttavia, sembra essere l'osservabilità (e controllabilità) a un livello più alto di astrazione. Ho paura che i mock o mozziconi di cui hai bisogno per questo dovrebbero essere progettati con cura e fatti a mano.

A livello di unità, questi finti possono essere generati correttamente, tramite Mockito. A livello di integrazione, questo diventa molto più difficile e avrete bisogno di interfacce di testabilità create appositamente.

+1

Sì, a livello di integrazione sembra che la gente faccia il meglio ", facendo tutto ciò che possono con le librerie di simulazione o colpendo effettivamente le istanze di test di servizi/database.Attualmente sto lavorando a un'estensione Mockito basata su Groovy per aiutare i test di integrazione ad essere un po 'meno doloroso. –

7

Al fine di prendere in giro le cose come banche dati, servizi web, il file system e così via, probabilmente si vuole di refactoring un po '. Per ogni servizio esterno, dovresti scrivere una classe wrapper che abbia un metodo per ogni operazione che desideri eseguire. Ciascuno di questi metodi non dovrebbe avere una logica effettiva, ma deve solo passare attraverso i suoi parametri nel modo in cui il servizio esterno comprenderà e restituire un oggetto che contiene i dati restituiti dal servizio esterno. Ad esempio, se si interagisce con un database, la classe wrapper potrebbe formattare i parametri in un'istruzione SQL, inviarli a un oggetto esistente Connection e restituire un valore List per il risultato.

Poiché i metodi della classe involucro contengono alcuna logica (cioè, no se/altro, senza anse e senza gestione delle eccezioni); non è necessario testare la classe dell'involucro.È necessario testare l'integrazione della classe wrapper, per assicurarsi che le sue responsabilità siano eseguite correttamente (ovvero che l'istruzione SQL abbia l'effetto desiderato sul database, ad esempio).

Ora riscrivere le classi che interagiscono con i servizi esterni in modo che interagiscano con le classi wrapper. È quindi facile testare le unità: devi solo prendere in giro le classi wrapper.

+0

Grazie David. I miei servizi esterni sono abbastanza astratti: ognuno è avvolto da una singola classe di servizio Spring Singleton. Anche con questo, per uno scenario complicato, la derisione diventa difficile. Vi sono molti dati che devono essere stubati, spesso lo stesso metodo di servizio verrà chiamato più volte, il che significa che ho bisogno che gli stub restituiscano più valori, quindi c'è il problema di ottenere quelli iniettati con Spring .. diventa peloso. Devo supporre che la gente abbia risolto questo in un modo più pulito –

+0

Devono essere avvolti con un singleton? I singleton sono notoriamente difficili da deridere. Puoi ingegnerizzare le cose in modo che il wrapper non sia un singleton? –

+0

Inoltre, vorrei sapere perché lo stesso metodo di servizio viene chiamato più volte all'interno di un test. Forse i tuoi metodi di test sono troppo grandi? Sono fermamente convinto della regola "un assert per test method"; fa davvero molto per test più puliti. –

0

Se è presente un framework di simulazione http o di riposo, l'utilizzo di questo dovrebbe essere positivo.

Tutte le complicate dipendenze possono essere registrate, modificate e riprodotte.

Problemi correlati