Un esempio di un caso di errore che dovresti prefiggere di catturare è che l'oggetto sottoposto a test utilizza un livello di memorizzazione nella cache ma non riesce a conservare i dati come richiesto. Quindi, se si esegue una query sull'oggetto, viene visualizzato il messaggio "Sì, ho il nuovo nome e indirizzo", ma si desidera che il test fallisca perché non ha effettivamente fatto ciò che doveva.
In alternativa (e trascurando la violazione della responsabilità singola), supponiamo che sia necessario mantenere una versione della stringa con codifica UTF-8 in un campo orientato al byte, ma in realtà persiste Shift JIS. Qualche altro componente leggerà il database e si aspetta di vedere UTF-8, da cui il requisito. Quindi il viaggio di andata e ritorno attraverso questo oggetto riporterà il nome e l'indirizzo corretti perché lo convertirà nuovamente da Shift JIS, ma l'errore non viene rilevato dal test. Si spera che venga rilevato da alcuni test di integrazione successivi, ma il punto centrale dei test unitari è quello di individuare i problemi in anticipo e sapere esattamente quale componente è responsabile.
Se uno di loro non sta facendo quello che dovrebbe, allora il suo caso di test fallirà e possiamo ripararlo ed eseguire nuovamente la batteria di prova.
Non puoi assumerlo, perché se non stai attento scrivi una serie di test reciprocamente dipendenti. Il "salva?" test chiama il metodo di salvataggio che sta testando, quindi il metodo di caricamento per confermarlo salvato. Il "carica?" test chiama il metodo save per impostare l'apparecchiatura di test e quindi il metodo di caricamento che sta testando per verificare il risultato. Entrambi i test si basano sulla correttezza del metodo che non stanno testando, il che significa che nessuno dei due verifica effettivamente la correttezza del metodo che sta testando.
L'indizio che c'è un problema qui è che due test che presumibilmente stanno testando unità diverse fanno effettivamente la stessa cosa . Entrambi chiamano un setter seguito da un getter, quindi controllano che il risultato sia il valore originale. Ma hai voluto verificare che il setter persista i dati, non che la coppia setter / getter funzioni insieme. Quindi sai che qualcosa non va, devi solo capire cosa e correggere i test.
Se il tuo codice è ben progettato per i test unitari, ci sono almeno due modi in cui puoi testare se i dati sono stati davvero correttamente persi con il metodo sotto test:
deride l'interfaccia del database e fa in modo che il tuo mock registri il fatto che sono state chiamate su di esso le funzioni appropriate, con i valori previsti. Questo test il metodo fa quello che dovrebbe, ed è il classico test unitario.
passarlo a un database effettivo con esattamente la stessa intenzione , per registrare se i dati sono stati correttamente conservati o meno. Ma invece di avere una funzione derisa che dice semplicemente "sì, ho i dati giusti", il tuo test legge direttamente dal database e conferma che è corretto. Questo potrebbe non essere il test più puro possibile, perché un intero motore di database è una cosa abbastanza grande da usare per scrivere una derisione glorificata, con più possibilità che io trascuri qualche sottigliezza che fa passare un test anche se qualcosa non va (quindi ad esempio non dovrei usare la stessa connessione al database per leggere come è stato usato per scrivere, perché potrei vedere una transazione senza commit). Ma mette alla prova la cosa giusta, e almeno lo sai esattamente implementa l'intera interfaccia del database senza dover scrivere alcun codice fittizio!
Quindi è solo un dettaglio dell'implementazione del test se leggo i dati dal database di test da JDBC o se derido il database. In ogni caso, il punto è che posso testare meglio l'unità isolandola che posso se permetto che cospiri con altri metodi errati sulla stessa classe per apparire bene anche quando qualcosa non va. Pertanto, desidero utilizzare qualsiasi mezzo conveniente per verificare che siano stati mantenuti i dati corretti, oltre a fidarmi del componente di cui sto testando il metodo.
Se il tuo codice non è ben progettato per il unit testing, allora potresti non avere scelta, poiché l'oggetto il cui metodo vuoi testare potrebbe non accettare il database come dipendenza iniettata. Nel qual caso la discussione sul modo migliore per isolare l'unità sotto test, si trasforma in una discussione su quanto è possibile arrivare a isolare l'unità sotto test. La conclusione è la stessa, però. Se riesci ad evitare cospirazioni tra unità difettose, lo fai, in base al tempo disponibile e a qualsiasi altra cosa tu pensi che sarebbe più efficace nel trovare guasti nel codice.