Ci sono due problemi che dobbiamo esaminare qui.
Il primo è che sembri guardare tutti i tuoi test dal punto di vista del test unitario. I test unitari sono estremamente preziosi, ma non sono gli unici tipi di test. I test possono in realtà essere suddivisi in diversi livelli, da test di unità molto veloci a test di integrazione meno veloci a test di accettazione ancora più lenti . (Possono esserci ancora più livelli suddivisi, come i test funzionali .)
Il secondo è che stai mescolando le chiamate al codice di terze parti con la tua logica aziendale, creando sfide di test e forse rendendo il tuo codice più fragile.
I test unitari dovrebbero essere veloci e dovrebbero essere eseguiti spesso. Deridere le dipendenze aiuta a mantenere veloci questi test, ma può potenzialmente creare buchi nella copertura se la dipendenza cambia e la derisione no. Il codice potrebbe essere rotto mentre i test sono ancora verdi. Alcune librerie beffardo ti avviseranno se l'interfaccia della dipendenza cambia, altre no.
I test di integrazione, d'altra parte, sono progettati per testare le interazioni tra i componenti, comprese le librerie di terze parti. I mock non dovrebbero essere usati a questo livello di test perché vogliamo vedere come l'oggetto reale interagisce insieme. Poiché stiamo usando oggetti reali, questi test saranno più lenti e non li eseguiremo con la stessa frequenza dei nostri test unitari.
I test di accettazione guardano a un livello ancora più elevato, verificando che i requisiti per il software siano soddisfatti. Questi test vengono eseguiti su tutto il sistema completo che verrebbe distribuito. Ancora una volta, non dovrebbe essere usato il beffardo.
Una linea guida che le persone hanno trovato preziosa per quanto riguarda le beffe è di non deridere i tipi che non possiedi . Amazon possiede l'API per S3 in modo che possano assicurarsi che non cambi sotto di loro. D'altra parte, non hai queste assicurazioni. Pertanto, se si deride l'API S3 nei test, potrebbe cambiare e rompere il codice, mentre i test tutti diventano verdi. Quindi, come possiamo testare l'unità di codice che utilizza librerie di terze parti?
Bene, non lo facciamo. Se seguiamo le linee guida, non possiamo prendere in giro oggetti che non possediamo. Ma ... se possediamo le nostre dipendenze dirette, possiamo deriderle. Ma come? Creiamo il nostro wrapper per l'API S3. Possiamo renderlo molto simile all'API S3 o possiamo adattarlo alle nostre esigenze più da vicino (preferito). Possiamo persino renderlo un po 'più astratto, diciamo un PersistenceService
piuttosto che un AmazonS3Bucket
. PersistenceService
sarebbe un'interfaccia con metodi come #save(Thing)
e #fetch(ThingId)
, i tipi di metodi che potremmo vedere (questi sono esempi, potresti effettivamente desiderare metodi diversi). Ora possiamo implementare un PersistenceService
intorno all'API S3 (diciamo a S3PersistenceService
), incapsulandolo lontano dal nostro codice chiamante.
Ora al codice che chiama l'API S3. Dobbiamo sostituire quelle chiamate con chiamate a un PersistenceService
oggetto. Usiamo l' iniezione di dipendenza per passare il nostro PersistenceService
nell'oggetto. È importante non chiedere un S3PersistenceService
, ma chiedere un PersistenceService
. Questo ci consente di scambiare l'implementazione durante i nostri test.
Tutto il codice che utilizzava direttamente l'API S3 ora utilizza il nostro PersistenceService
e il nostro S3PersistenceService
ora effettua tutte le chiamate all'API S3. Nei nostri test, possiamo deridere PersistenceService
, dal momento che lo possediamo, e usare il mock per assicurarci che il nostro codice effettui le chiamate corrette. Ma ora questo lascia come testare S3PersistenceService
. Ha lo stesso problema di prima: non possiamo testarlo unitamente senza chiamare il servizio esterno. Quindi ... non lo testiamo. Abbiamo potuto deridere le dipendenze S3 API, ma questo ci darebbe poco a sfiducia supplementare. Invece, dobbiamo testarlo a un livello superiore: test di integrazione.
Questo può sembrare un po 'preoccupante dire che non dovremmo testare una parte del nostro codice, ma diamo un'occhiata a ciò che abbiamo realizzato. Avevamo un sacco di codice in tutto il luogo in cui non potevamo test unitari che ora possono essere testati attraverso il PersistenceService
. Il nostro disordine di libreria di terze parti è limitato a una singola classe di implementazione. Tale classe dovrebbe fornire le funzionalità necessarie per utilizzare l'API, ma non ha alcuna logica aziendale esterna ad essa collegata. Pertanto, una volta scritto, dovrebbe essere molto stabile e non dovrebbe cambiare molto. Possiamo fare affidamento su test più lenti che non eseguiamo così spesso perché il codice è stabile.
Il prossimo passo è scrivere i test di integrazione per S3PersistenceService
. Questi dovrebbero essere separati per nome o cartella in modo che possiamo eseguirli separatamente dai nostri test di unità veloci. I test di integrazione possono spesso utilizzare gli stessi framework di test dei test unitari se il codice è sufficientemente informativo, quindi non è necessario apprendere un nuovo strumento. Il codice effettivo per il test di integrazione è ciò che scriveresti per l'opzione 1.