Di recente ho guardato Test di integrazione sono una truffa di JB Rainsberger e ora sto cercando altro materiale sull'argomento. Devo dire che sono scioccato da quanto stiamo sbagliando (cioè test di integrazione quando dovremmo testare l'unità), incuriositi dai concetti descritti da Rainsberger ma anche confusi su come applicarli. Vorrei avere più dei test di collaborazione e dei test contrattuali descritti ma non so da dove iniziare.
Le uniche cose che mi sono rimaste impresse sono le 4 domande che i test devono porre:
Lato A:
Do I ask the right question?
Can I deal with the answer?
Lato B:
Can I answer a question?
Do I answer correctly?
Ma come posso applicarlo ad un metodo casuale nel mio stack di applicazioni?
Esiste un libro o un tutorial o un esempio là fuori che prende un esempio del mondo reale e applica queste idee di micro test isolati? Idealmente, l'esempio utilizza Java, Spring + PowerMock / Mockito / EasyMoock
Ogni letteratura che tratta questi concetti in generale e mi aiuta a capirli meglio sarebbe apprezzata.
Inoltre, se ci sono forum là fuori dove posso porre domande più dettagliate su come procedere correttamente sui test unitari e magari anche rifattorizzare il codice esistente e pubblicare esempi sarebbe bello.
Grazie!
Modifica: alcuni pensieri aggiuntivi:
C'è una regola generale, quando usare un mock e quando uno stub per isolare una classe sotto test dai suoi collaboratori? Può essere applicato alle 4 domande?
I migliori framework di derisione sembrano essere PowerMock, permettendomi di definire precocemente per ogni test quale classe voglio prendere in giro e cosa dovrebbe restituire o c'è qualcosa di meglio che hai usato per porre le domande di cui sopra? Ci sono buone esercitazioni là fuori che usano PowerMock per applicare alcuni o tutti i principi dati ad alcune parti di uno stack di applicazioni reali, ad esempio un DAO o una GUI?
Modifica 2 - un esempio
Solo alcuni esempi del tipo di metodi che voglio testare e dei miei pensieri ..
Ho un servizio web che salva gli ordini. In questa fase non siamo troppo preoccupati per la migliore sicurezza, quindi per avere alcuni, il servizio richiederà anche un nome utente e una password per autenticare la richiesta di salvataggio. Una volta autenticato, viene chiamato OrderManager
per salvare Order
. Internamente il gestore decide se è un nuovo ordine, quindi deve essere creato o esistente che deve essere aggiornato. (Ciò non dovrebbe importare nel WebSerice, giusto?)
@WebService
public class OrderService {
@Inject
private AuthenticationManager authenticationManager;
@Inject
private OrderManager orderManager;
public void save(String username, String password, Order order) {
authenticationManager.authenticate(username, password);
try {
orderManager.save(orde);
} finally {
authenticationManager.logout();
}
}
Ora mi chiedo: cosa sto testando esattamente qui? Sto pensando che ci dovrebbero essere test per il successo e l'insuccesso dell'autenticazione e per l'ordine di successo e fallimento.
Ma come posso suddividerlo nelle 4 domande? La mia classe in Test è ovviamente OrderService
(OS) ei collaboratori sono OrderManager
(OM) e AuthenticationManager
. (AM)
Quindi ho i seguenti test, per favore correggimi qui, sto solo pensando ad alta voce:
OS < - > OM
- Il sistema operativo chiede a OM di salvare un ordine (quale tipo di parametri diversi faccio test qui?
null
eOrder
? Importa seOrder
è inizializzato correttamente?) - OM risponde a una chiamata di salvataggio chiamando un altro metodo interno, io verifico se quel metodo viene richiamato?!
- Il sistema operativo non dovrebbe fallire se OM non fallisce
- Il sistema operativo dovrebbe fallire se OM fallisce
... Cos'altro?
E poi ovviamente OS < - > AM :
-
Il sistema operativo
- chiede ad AM di autenticarsi - suppongo di testare come l'AM reagisce a diversi tipi di username / password?
- ...
Ora la mia prima conclusione :
Per quanto riguarda WebSerice, posso testare solo 2 domande su 4: Lato A. Ora devo guardare OrderManager
e AuthenticationManager
e vedere se possono rispondere alle domande del lato B. Giusto ?
In secondo luogo - accesso al database:
L'autenticazione e la persistenza dell'ordine richiedono ovviamente alcuni dati nel database in un ambiente di produzione. Per le mie unit test però non mi serviranno quindi mi limiterò a prendere in giro le chiamate per restituire il risultato desiderato, giusto? Ma come faccio a deridere questo?
Ho bisogno di AuthenticationManager.authenticate
per fare praticamente nulla, in quanto in caso di autenticazione fallita getterà un Exception
, altrimenti ha il tipo di ritorno void
. Come faccio a dire al mio OrderService.save()
di usare il mio% deriso% co_de?
E come faccio a impostare AuthenticationManager.authenticate()
su o non fare nulla o lanciare un'eccezione?
Posso dire a Spring di iniettare un% co_de deriso che non farà nulla / gettare un AuthenticationManager
nel mio AuthenticationManager
sotto test?