Unità che verifica un metodo vuoto


13

Per correggere un bug in un'applicazione, ho modificato un metodo denominato postLoginaggiungendo una chiamata a un metodo esistente denominato getShoppingCart.

Codice

protected void postLogin() {
  getShoppingCart();
}

Tuttavia, non sono sicuro di quale sia il modo migliore per scrivere un test unitario postLogin.

Approccio 1

Usa verifica da Mockito per verificare semplicemente che il metodo è stato chiamato.

verify(mock).getShoppingCart();

Approccio 2

Prova l'effetto collaterale della chiamata del metodo recuperando il valore del carrello dell'utente.

AssertNotNull(user.getShoppingCart());

Un approccio è migliore dell'altro?


1
a prescindere dal fatto che il test sia più facile da capire e mantenga pulito il codice. Se non si è sicuri della progettazione del test, che POTREBBE anche essere un segno che la progettazione del codice è disattivata. Assicurati di porre queste domande: " PERCHÉ l' aggiunta di quella chiamata al metodo risolve il bug? È questo il modo GIUSTO per correggere questo bug?"
Caleb,

8
A meno che il getShoppingCart()metodo non abbia effetti collaterali, non è necessario verificare che venga chiamato. Se ha effetti collaterali, dovresti davvero cambiarne il nome perché i getXXX()metodi convenzionalmente dovrebbero essere idempotenti.
Jules il

@Jules getNextValue? Probabilmente qualcuno potrebbe dire "Non chiamarlo getter; cambia il nome in nextValue", ma l'ho già visto getNextusato prima. Forse un esempio migliore sarebbe un oggetto che rappresenta un elettrone; cosa succede quando chiamo getPosition? O peggio,getPosition(); getVelocity();
Aaron,

Risposte:


18

Preferirei di solito il metodo 2.

Perché? Perché, vuoi postLogincambiare un certo stato del tuo sistema, ma il modo in cui lo fa (e quali metodi chiama internamente per questo) è solo un dettaglio di implementazione, nulla su cui il tuo test unitario dovrebbe fare ipotesi. Quindi meglio fare il test solo verificando lo stato finale.


4

Vorrei cambiare getShoppingCart in qualcosa di simile a initializeShoppingCart, lo scopo del metodo dovrebbe essere chiaro a chiunque lo legga senza la necessità di verificare cosa fa il metodo e gli effetti collaterali come questo possono causare un comportamento sorprendente per gli utenti del metodo.

Se getShoppingCart è in un'altra classe ed è già testato in unità, utilizzerei l'approccio 1 - non è necessario testare di nuovo ciò che è già stato testato. In questo caso siamo sicuri che getShoppingCart funzioni correttamente e vogliamo solo assicurarci che venga chiamato da postLogin, quindi se in futuro qualcuno rimuoverà questa chiamata, il test fallirà.

Se getShoppingCart è un metodo privato che non può essere testato da solo, utilizzerei l'approccio 2, per assicurarmi che quando postLogin viene chiamato la funzionalità desiderata di getShoppingCart viene eseguita come previsto.


1

Quando si verifica una chiamata di funzione (nulla o meno) che ha un effetto collaterale, è più completo testare che l'effetto collaterale non si verifica solo, ma per verificare che l'effetto collaterale (uscita del sistema o cambio di stato) sia quello desiderato.


1
Sebbene ciò sia vero, vale anche la pena considerare che i dettagli dell'effetto collaterale che si verificano potrebbero far parte dello stato interno di qualche altro modulo e che, controllando tali dettagli, si accoppierebbe il test non solo al modulo che sta testando ma anche quell'altro modulo, che potrebbe portare a fragili test se è probabile che quei dettagli cambino. Deridere l'interfaccia tra i moduli aiuta a prevenire questo problema.
Jules il

0

Non discuterò del tuo progetto, ma nel tuo caso preferirei il primo approccio perché l'unità di test è per testare quali metodi tecnicamente fanno indipendentemente dal loro lavoro nel dominio, cioè quale metodo postLoginfa? Tecnicamente chiama getShoppingCardquindi devi testare quello che sta davvero chiamando getShoppingCard, vorrei anche creare un altro test per getShoppingCardtestare quello che fa e se ha effetti collaterali lo controllerò all'interno di quel nuovo test.


0

Hai un bug in postLogin. Quindi la prima cosa da fare è creare un unit test che dopo aver chiamato postLogin senza l'insieme previsto di informazioni "fallirà".

Dall'idea di cui sopra, un'altra alternativa alla 2 proposta è quella di iniettare le informazioni sul carrello come parametro. Se non si dispone delle informazioni corrette, si genera un'eccezione non selezionata. Ciò chiarirà che senza i dettagli corretti, il tuo metodo è condannato.

Ciò richiederà una piccola modifica in cui il cliente che chiama subito PostLogin è tenuto a passare anche le informazioni del carrello. Per me questo è ancora coerente ora che vedi che sono accoppiati. Questo accoppiamento verrà eseguito dal chiamante.

Quindi non avresti nemmeno bisogno di testare getShoppingCart all'interno di postLogin perché il vero metodo sotto test è postLogin. È quello che ha il bug e l'unico che richiede una corretta correzione e convalida. Con la dipendenza iniettata, sarai in grado di testarlo facilmente in condizioni diverse e confermare che non viene generato alcun errore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.