Un sacco di scherno quadri stanno portando i concetti di mock & stub più stretti & più vicini al punto che essi possono essere considerati funzionalmente quasi la stessa. Dal punto di vista concettuale però, io di solito cerco di seguire questa convenzione:
- Mock: Solo quando si sta esplicitamente cercando di verificare il comportamento dell'oggetto in prova (cioè il test sta dicendo che questo oggetto deve chiamare quell'oggetto).
- Stub: Quando si tenta di testare alcune funzionalità/comportamento, ma per farlo funzionare è necessario fare affidamento su alcuni oggetti esterni (ad esempio il test sta dicendo che questo oggetto deve fare qualcosa, ma come un lato effetto, essa può avvalersi quell'oggetto)
Ciò diventa più chiaro quando vi assicurate che ognuno dei vostri test di unità unica prova una cosa. Certo, se provi a testare tutto in un test, tanto vale aspettarti di tutto. Ma aspettando solo le cose che il test di unità specifico sta cercando, il tuo codice è molto più chiaro perché puoi vedere a colpo d'occhio qual è lo scopo del test.
Un altro vantaggio di questo è che sarete leggermente più isolati dal cambiamento & ottenere migliori messaggi di errore quando una modifica provoca un'interruzione. In altre parole, se si sottrae una parte della propria implementazione, è più probabile che si verifichi una rottura del test case, che vi mostrerà esattamente ciò che è rotto, piuttosto che un'intera serie di test che rompono & creando solo rumore.
Edit: Potrebbe essere più chiaro sulla base di un esempio forzato in cui gli audit un oggetto calcolatrice tutte le aggiunte ad un database (in pseudo-codice) ...
public void CalculateShouldAddTwoNumbersCorrectly() {
var auditDB = //Get mock object of Audit DB
//Stub out the audit functionality...
var calculator = new Calculator(auditDB);
int result = calculator.Add(1, 2);
//assert that result is 3
}
public void CalculateShouldAuditAddsToTheDatabase() {
var auditDB = //Get mock object of Audit DB
//Expect the audit functionality...
var calculator = new Calculator(auditDB);
int result = calculator.Add(1, 2);
//verify that the audit was performed.
}
Quindi nel primo caso test che abbiamo 'testando la funzionalità del metodo Add
& non importa se un evento di verifica si verifica o meno, ma sappiamo che la calcolatrice non funzionerà senza un riferimento di auditDB, quindi lo stubmo solo per darci il minimo di funzionalità per far funzionare il nostro caso di test specifico.Nel secondo test stiamo testando specificamente che quando si fa un Add
, si verifica l'evento di controllo, quindi qui usiamo le aspettative (notiamo che non ci interessa nemmeno quale sia il risultato, dal momento che non è quello che stiamo testando).
Sì, è possibile combinare i due casi in uno, & fare aspettative e affermare che il risultato è 3, ma poi si stanno testando due casi in un test di unità. Ciò renderebbe i test più fragili (poiché c'è una superficie più ampia di cose che potrebbero cambiare per interrompere il test) e meno chiaro (poiché quando il test combinato fallisce non è immediatamente evidente quale sia il problema .. l'aggiunta non funziona, o l'audit non funziona?)
L'attesa restituirà nulla mentre Stub restituirà ciò che viene specificato. entrambi "stub" il metodo una volta – zinking