2015-04-17 11 views
7

questo blog article dice che:Perché il mocking con DI è migliore di quello degli oggetti di simulazione in ogg-c?

Mentre ci sono modi a volte ragionevoli per deridere fuori oggetti senza DI (tipicamente deridendo i metodi di classe, come si è visto in precedenza l'esempio OCMock ), è spesso flat out non è possibile . Anche quando è possibile, la complessità della configurazione di test potrebbe superare i benefici. Se stai utilizzando l'iniezione delle dipendenze in modo coerente, troverai la scrittura dei test usando stub e le presentazioni saranno molto più semplici.

ma non spiega perché. Cosa sono possibili scenari dove DI (iniettando un oggetto id conforme al protocollo) servirà meglio scherno in Objective-C, di semplice OCMockito:

[given([mockArray objectAtIndex:0]) willReturn:@"first"]; 
[verifyCount(mockArray, times(1)) objectAtIndex:]; 

?

risposta

1

Ho notato che è più facile creare una classe separata per il target di test quando la classe originale esegue alcune operazioni asincrone.

Supponiamo di scrivere un test per UIViewController che ha una dipendenza LoginSystem che utilizza AFNetworking per eseguire una richiesta all'API. LoginSystem accetta un argomento di blocco come callback. (UIViewController-> LoginSystem-> AFNetworking).

Se si esegue una simulazione di LoginSystem probabilmente si finirà con i problemi su come attivare un blocco di callback per verificare il comportamento di UIViewController in caso di successo/fallimento.Quando ho provato ho finito con MKTArgumentCaptor per recuperare un argomento di blocco e poi ho dovuto richiamarlo in un file di test.

D'altra parte, se si crea una classe separata per LoginSystem (chiamiamola LoginSystemStub che si estende da LoginSystem) si è in grado di "deridere" un comportamento in 3 righe di codice e all'esterno del file di test. Dovremmo anche mantenere il nostro file di test pulito e leggibile.

Un altro caso è che verify() non funziona con il controllo del comportamento asincrono. È molto più facile chiamare expect (smth2). sarà .equal (si dovrebbe occupare)

EDIT:

Puntatori a NSError (NSError **), inoltre, non funzionano bene con verify() ed è meglio per creare uno stub: D

+0

Grazie :) Quindi penso che si adatti al mio statemenet "È meglio solo se hai bisogno di un comportamento super custom." –

0

Immaginate di provare a testare un comportamento più complesso di un oggetto che interagisce con uno dei suoi oggetti figli. Per assicurarsi che l'oggetto padre funzioni correttamente, è necessario prendere in giro tutti i metodi dell'oggetto figlio e persino tracciare il proprio stato di modifica.

Ma se lo fai, hai appena scritto un oggetto completamente nuovo in modo confuso e contorto. Sarebbe stato più semplice scrivere un oggetto completamente nuovo e dire al genitore di usarlo.

+0

Are stai implicando che usare DI per ogni dipendenza con tutta la confusione che introduce e quindi creare una classe di simulazione separata è in qualche modo più pulita/meno complicata dello stub di OCMockito? Io non la penso così –

+0

Nella maggior parte dei casi il rilevamento dello stato di modifica di una simulazione sembra inutile. L'unica cosa di cui hai bisogno da una simulazione è che restituisca alcuni dati e scopri se sono stati chiamati determinati metodi. –

0

Con DI si inserisce il modello in fase di esecuzione, non è associato alle classi ma solo alla configurazione.
Quando vuoi prendere in giro devi solo creare un modello di simulazione e iniettarlo invece dei tuoi dati reali. Oltre al modello, hai cambiato la tua implementazione in una singola riga.

Vedere here per un esempio di mani o here per l'idea alla base.

Disclaimer: Naturalmente è possibile prendere in giro altre cose oltre al modello, ma probabilmente è il caso d'uso più comune.

+0

Sì, so come prendere in giro l'uso di lezioni di simulazione. Volevo solo sapere se usare le classi reali è superiore a quello che ho detto nel blog, e se lo è, perché? –

0

La risposta è: non è meglio. È solo meglio se hai bisogno di un comportamento super personalizzato.

La cosa migliore è che non è necessario creare un'interfaccia/protocollo per ogni classe che si inietta e si può limitare a DI i moduli effettivamente necessari per iniettare rendendo il codice più pulito e più YAGNI.

Si applica a qualsiasi lingua dinamica o lingua con riflessione. Creare troppa confusione solo per motivi di unit test mi ha colpito come una cattiva idea.

Problemi correlati