Domanda

Io uso NMock2, e ho redatto le seguenti classi NMock per rappresentare alcuni concetti quadro finti comuni:

  • Expect: questa specifica quale un metodo deriso deve restituire e dice che deve avvenire la chiamata o il test fallisce (se accompagnati da una chiamata a VerifyAllExpectationsHaveBeenMet())

  • .
  • Stub: questa specifica quale un metodo deriso deve restituire, ma non può causare un fallimento del test

  • .

Così che devo fare quando?

È stato utile?

Soluzione

Un sacco di quadri di scherno stanno portando i concetti di schernisce e mozziconi più vicini e più vicini al punto che essi possono essere considerati funzionalmente quasi lo stesso. Dal punto di vista concettuale però, io di solito cerco di seguire questa convenzione:

  • Mock :. Solo quando si sta tentando in modo esplicito per verificare il comportamento dell'oggetto in prova (vale a dire il test sta dicendo che questo oggetto deve chiamare l'oggetto)
  • Stub : Quando si sta tentando di testare alcune funzionalità / comportamento, ma al fine di ottenere che il lavoro è necessario fare affidamento su alcuni oggetti esterni (cioè il test sta dicendo che questo oggetto deve fare qualcosa , ma come effetto collaterale, essa può avvalersi quell'oggetto)

Questo diventa più chiaro quando vi assicurate che ognuno dei vostri test di unità unica prova una cosa. Certo, se si tenta di verificare tutto in una prova, allora si potrebbe anche aspettare di tutto. Ma solo da aspettarsi le cose che prova specifica unità sta controllando per, il codice è molto più chiara, perché si può vedere a colpo d'occhio qual è lo scopo del test è.

Un altro vantaggio di questo è che ti verrà un po 'più isolato dal cambiamento e ottenere una migliore messaggi di errore quando un cambiamento provoca una pausa. In altre parole, se il cambiamento subtley qualche parte della vostra implementazione, la tua più probabilità di trovare una sola prova caso di rottura, che vi mostrerà esattamente ciò che è rotto, invece di una suite completa di test di rottura e solo la creazione di rumore.

Modifica : Potrebbe essere più chiaro sulla base di un esempio forzato in cui un audit calcolatrice oggetto tutte le aggiunte a 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 banco di prova stiamo testando la funzionalità del metodo Add e non importa se si verifica un evento di controllo o no, ma ci capita di sapere che la calcolatrice non funziona con un riferimento fuori AUDITDB così abbiamo appena stub fuori per darci il minimo di funzionalità per ottenere il nostro banco di prova specifica di lavoro. Nella seconda prova stiamo testando in particolare che quando si fa un Add, l'evento di controllo accade, ecco usiamo le aspettative (si noti che non ci interessa nemmeno quello che il risultato è, dal momento che non è quello che stiamo testando).

Sì, è possibile combinare i due casi in una sola, e fare le aspettative e affermare che il risultato è 3, ma poi si sta testando due casi in una sola unit test. Questo renderebbe i test più fragili (dal momento che c'è una maggiore superficie delle cose che potrebbero cambiare per rompere il test) e meno chiaro (da quando il test di fusione fallisce la sua non è immediatamente evidente quale sia il problema .. è l'aggiunta non funziona, o è l'audit non funziona?)

Altri suggerimenti

"Aspettatevi azioni, query stub". Se la chiamata dovrebbe cambiare lo stato del mondo al di fuori dell'oggetto in prova, poi ne fanno un'aspettativa - vi preoccupate per come viene chiamato. Se è solo una query, si può chiamare una o sei volte senza modificare lo stato del sistema, quindi la chiamata stub.

Ancora una cosa, si noti che la distinzione è tra i mozziconi e le aspettative, cioè le chiamate individuali, non necessariamente interi oggetti.

Beh ... IMHO non può essere più semplice: se il test è di garantire il vostro Presenter chiamerà salvare, effettuate una aspettano. se il test è di garantire la vostra Presenter consente di gestire con garbo eccezione se Salva getta, fare uno stub.

Per ulteriori dettagli, visitate questo podcast da Hanselman e Osherove (autore di l'arte di Unit Testing)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top