Faking - Dipendenza vs dettagli interni

5

Solo per il gusto della discussione qui sotto, quando mi riferisco al mocking, intendo il mocking / stubbing / finging, come contrasto per usare l'implementazione reale nei test

Ho appena avuto qualche discussione con il mio collega durante una sessione di programmazione di coppia riguardo a se dovremmo usare il mocking nei test unitari per il nostro codice scritto. (Non sono sicuro che questo sia importante, ma siamo una coppia in programmazione su una base di codice Ruby / Rails)

Il suo argomento è che non dovremmo usare il mocking se è il nostro codice scritto. Il mocking dovrebbe essere usato solo per estrapolare dipendenze esterne (.e.g. Sistema di terze parti). Diciamo che se ci sono classi A e B, e A dipende da B (.eg uno dei metodi di A crea e usa B), ha detto che non dovremmo prendere in giro B quando testiamo A (sia A che B sono scritti e mantenuti da noi ), poiché B è i dettagli di implementazione interna di A.

Anche se sono d'accordo con lui fino ad un certo punto, trovo ancora alcuni casi in cui è necessario e richiesto il nostro codice di simulazione:

  • In primo luogo, credo che se non prendiamo in giro le dipendenze di una classe, non è più un test unitario. Quindi, come nell'esempio sopra, stiamo scrivendo test di integrazione per le classi A e B. Non sto dicendo che i test di integrazione non siano necessari, ma ci sono alcuni svantaggi rispetto al test unitario, ad esempio. eseguire più lentamente e quando un test non riesce, è necessario tracciare il codice di implementazione per identificare i componenti che causano l'errore. E quindi dovremmo chiarire cosa è il test unitario, che cos'è il test di integrazione
  • In secondo luogo, non dovremmo testare e preoccuparci dei dettagli di implementazione di una classe finché il contratto pubblico continuerà a essere mantenuto. Tuttavia, credo che dovremmo testare l'interazione di una classe con le sue dipendenze (peer?) Poiché tali interazioni sono comportamenti previsti di quella classe. In alcuni casi, non è facile determinare quali siano i dettagli dell'implementazione e quale sia la dipendenza, ad esempio. in un'applicazione a livelli (controller - > servizio applicazioni - > dominio), è una dipendenza del servizio applicativo o implementazione interna di un controller?

Quindi le mie domande sono:

  • Quali sono le tue opinioni su quando e dove usare il mocking?
  • Qualsiasi buona euristica per decidere cos'è la dipendenza e quali sono i dettagli di implementazione interna? Prendi ad esempio l'applicazione sovrapposta sopra

Non sono sicuro che sia perché il mio background è in C #, trovo difficile accettare l'idea che il mocking non è necessario quando testiamo il nostro codice

    
posta Phuong Nguyen 17.10.2016 - 14:45
fonte

3 risposte

2

His argument is that we should not use mocking if it's our own written code. Mocking should be used only to stuffs out external dependencies (.e.g. third party system)

Il mocking dovrebbe essere usato solo se assolutamente necessario, poiché ogni finto significa che stai testando come si comporta un codice quando connesso a quel simulato, piuttosto che al codice reale.

Vedi Smetti di usare mock , lungo siwth Scopri te stesso, non i tuoi test e molti altri articoli facilmente ricercabili sul perché il mocking dovrebbe essere evitato.

Let's say if there are class A and B, and A depends on B (.e.g. one of A's method creates and uses B)

B è una classe pubblica? In tal caso, A non dovrebbe creare un'istanza di B ; questo è un accoppiamento stretto. Invece, A deve essere passato un'istanza dell'interfaccia IB o IBFactory da cui può richiedere un'istanza IB . Se B si comporta bene con un comportamento deterministico e nessun effetto collaterale esterno, può anche essere usato direttamente quando si prova A .

First, I believe if we don't mock dependencies of a class, it's no longer unit test.

Scusa ma è una sciocchezza. Un test unitario è un test di un'unità di codice che può essere eseguito in parallelo con altri test senza influenzare tali test e senza effetti collaterali esterni. Quella unità di codice potrebbe essere una funzione, una raccolta di funzioni (ad esempio una classe) o quasi l'intero sistema, purché non abbia effetti collaterali o influenzi altri test.

What are your opinions on when and where to use mocking?

Usi il mocking solo quando non può essere evitato.

Any good heuristics to decide what is dependency and what is internal implementation details?

La dipendenza è pubblica? Se è così, allora non è un dettaglio di implementazione. Se non è pubblico, è in effetti un dettaglio di implementazione, ma è anche una dipendenza (e se si tratta di un dettaglio di implementazione non dovrebbe assolutamente essere deriso perché i test non dovrebbero andare vicino ai dettagli di implementazione.)

    
risposta data 17.10.2016 - 15:14
fonte
1

Ci sono tre buoni argomenti per l'utilizzo di Mock (e per mock, intendo quegli elementi creati da un framework come Mocha che ti permette di affermare se è stato chiamato il mock):

  • È importante sapere che l'oggetto in prova chiama correttamente e coerentemente l'altro oggetto in un modo specifico e / o un numero specifico di volte.
  • È importante prevenire gli effetti collaterali che potrebbero essere causati chiamando altri metodi di oggetto.
  • È importante isolare l'unità di codice che si desidera testare per individuare la causa dei guasti, proprio come sottolinea @Callum nel suo commento sulla risposta di David Arno.

Se non ti interessa di questi elementi, i mazzi non sono realmente necessari.

    
risposta data 17.10.2016 - 21:45
fonte
1

C # anche qui sfondo. Potresti voler cercare l'approccio 'mockista' (aka London) al TDD (al contrario di quello classico / di Detroit). Personalmente l'ho usato con grande successo in molti progetti commerciali, e ho trovato che fosse il modo migliore per testare le mie unità in perfetto isolamento. Si finisce con un design incredibilmente disaccoppiato in questo modo.

Non ascoltare le persone che ti dicono di fare affidamento sui test di integrazione. I test di integrazione sono una truffa , perché non c'è verso che tu possa coprire tutte le combinazioni di casi limite all'interno della catena di unità che il test di integrazione è presumibilmente test. Concentrati sull'avere unità perfettamente testate, e l'intero sistema funzionerà solo quando componi il tuo oggetto grafico (di solito faccio un paio di test di integrazione come controllo di integrità).

Consiglio vivamente il seguente libro, specialmente i primi capitoli che spiegano perfettamente l'approccio mockista al TDD: Crescere il software orientato agli oggetti, guidato dai test

Per quanto riguarda la tua domanda su cosa deridere? Prendo in giro tutto ciò che non è sotto test. Di solito significa prendere in giro le interfacce delle dipendenze che vengono iniettate nel costruttore della classe sottoposta a test dell'unità. Con C # abbiamo il vantaggio di avere accesso a Moq, che non è solo molto potente, ma anche molto conciso e leggibile.

    
risposta data 19.10.2016 - 04:06
fonte

Leggi altre domande sui tag