In che modo gli oggetti finti vengono comunemente usati in modo improprio?


15

Di recente ho letto un articolo in cui si diceva che gli oggetti finti sono spesso fraintesi e abusati. Ci sono dei chiari anti-schemi beffardi che posso cercare?


è l'articolo che leggi questo? martinfowler.com/articles/mocksArentStubs.html
keppla

no ... non ricordo la fonte esatta ma pubblicherò qui se lo faccio
Armand,

Sono stato portato al compito su StackOverflow per deridere l'API mongodb. Mi è stato indicato un post sul blog in cui si afferma che è sbagliato deridere qualsiasi classe che tu stesso non abbia scritto. In realtà non sono d'accordo con questo, ma l'opinione è là fuori.
Kevin,

Risposte:


13

Odio vedere derise semplici classi concrete. Ad esempio, prendi la seguente semplice classe che non ha dipendenze da nient'altro:

public class Person
{
    private readonly string _firstName;
    private readonly string _surname;

    public Person(string firstName, string surname)
    {
        if (String.IsNullOrEmpty(firstName))
        {
            throw new ArgumentException("Must have first name");
        }

        if (String.IsNullOrEmpty(surname))
        {
            throw new ArgumentException("Must have a surname");
        }

        _firstName = firstName;
        _surname = surname;
    }

    public string Name 
    {
        get
        {
            return _firstName + " " + _surname;
        }
    }
}

In tutti i test che coinvolgono questa classe, preferirei che ne venisse istanziata e usata una vera e propria piuttosto che estrarre un'interfaccia come "IPerson", una beffa usata e aspettative impostate. Usando quello reale il test è più realistico (hai i controlli dei parametri in atto e l'implementazione reale della proprietà 'Nome'). Per una classe semplice come questa non stai rendendo i tuoi test più lenti, meno deterministici o confondendo la logica (non è probabile che tu abbia bisogno di sapere che il nome è stato chiamato durante il test di un'altra classe) - che sono le solite ragioni per deridere / sradicamento.

Come estensione di questo ho anche visto persone scrivere test in cui il mock è impostato con un'aspettativa, quindi il mock viene chiamato direttamente nel test. Senza sorprese il test passerà sempre ... hmmmm ...


Per fortuna deridere i framework che ho usato sono stati in grado di deridere classi concrete, quindi estrarre interfacce in punti scomodi non è un problema.
Armand,

5
Ciò non cambia il problema: questo genere di cose semplici in genere non dovrebbero essere derise anche se stai usando qualcosa che allenta i vincoli tecnici su ciò che può essere deriso (ad esempio un framework simulato come TypeMock o un linguaggio dinamico).
Finlandia,

La mia regola empirica è sempre stata quella di deridere il comportamento, non i dati.
Ardave,

10

Potrebbe sembrare ovvio, ma: non usare oggetti finti nel codice di produzione! Ho visto più di un esempio in cui il codice di produzione dipendeva dalle caratteristiche di alcuni oggetti finti ( MockHttpServletRequestad esempio da Springframework).


14
spero che tu abbia seguito il tuo santo dovere e abbia inviato il codice a DailyWTF?
keppla,

1
Nel mio lavoro precedente ci era espressamente vietato inviare qualsiasi cosa dalla nostra base di codice a DWTF.
quant_dev,

9
@quant_dev: il fatto che avessero una tale politica implica cose spaventose per i loro sviluppatori ...
John Fisher,

1
Non proprio. È stata una startup che ha dovuto sviluppare rapidamente una base di codice per vendere un prodotto, quindi ha iniziato a consolidarlo e riformattarlo per ripagare il debito tecnico, poiché il prodotto è maturato e l'ulteriore sviluppo è stato ostacolato dalla (mancanza di) progettazione iniziale. I manager sapevano che la vecchia base di codice era merda e investivano tempo e risorse nel refactoring, ma non volevano rischiare alcuna pubblicità negativa.
quant_dev,

Basta prendere scorciatoie non è abbastanza per darti solo dailywtf ...
poolie,

9

Secondo me è l'eccessivo controllo dell'invocazione del metodo su beffe. Sento che questa è una pratica applicata da alcuni framework di derisione come EasyMock, in cui il comportamento di simulazione predefinito fallisce ogni volta che viene invocata una metodologia aggiuntiva che ciò che non era stato specificato in precedenza. Questo tipo di rigoroso controllo del metodo simulato può portare a progetti fragili in cui la più piccola modifica al codice può portare a un'intera serie di test che falliscono, anche se la funzionalità di base è sempre la stessa.

Una soluzione a questo sta iniziando a usare gli stub invece dei mock. Un articolo che ho trovato particolarmente illuminante sull'argomento è stato trovato in Javadoc di Mockito: http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html (vedi "2. Che ne dici di un po 'di stub?" ), che collega a: http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/ .

Finora mi sono divertito a lavorare con Mockito perché non impone questo rigoroso comportamento beffardo ma l'uso di stub. Applica inoltre il controllo del metodo su quelli specifici invece dell'intero oggetto simulato; quindi finisci per controllare solo i metodi che contano davvero nel tuo scenario di test.

Ci sono alcuni libri qua e là che posso consigliare di toccare questo argomento, beffardo e generale:

xUnit Patterns

L'arte del test unitario: con esempi in .Net

Test Java di prossima generazione: TestNG e Advanced Concepts (questo libro tratta principalmente di testNG ma c'è un bel capitolo sul deridere)


+1 per il punto sui controlli di invocazione del metodo eccessivo. Tuttavia, c'è sempre il rovescio della medaglia in cui un'invocazione del metodo imprevista provoca un errore nel metodo. Per fortuna Mockito ha l' Answer.RETURNS_SMART_NULLSimpostazione per le beffe che aiuta a diagnosticare questo.
Bringer128,

4

Ho osservato alcuni anti-schemi nella mia esperienza.

  • Classi di dominio oggetto di derisione / stub in cui potrebbe verificarsi un cambiamento di stato e che deve essere verificato.
  • Test di integrazione che interagiscono con un mix di simulazioni e classi concrete che vanifica lo scopo dei test di integrazione.
  • Uso involontario di beffe nel codice di produzione (questo non dovrebbe mai accadere)

Altrimenti la mia esperienza con le beffe in particolare Mockito è stata un gioco da ragazzi. Hanno reso i test molto facili da scrivere e gestire. Il test di interazione con GWT view / presenter è molto più semplice con simulazioni rispetto a GWTTestCase.


2 e 3 sono problemi definiti! Hai un semplice esempio di (1)?
Armand,

2

Trovo che i test che utilizzano simulazioni su più livelli di un'applicazione siano particolarmente difficili da decifrare e modificare. Tuttavia, penso che questo sia stato mitigato negli ultimi anni da API mock framework migliorate (uso JMock dove conveniente).

5 o 6 anni fa le API come EasyMock erano potenti ma molto ingombranti. Spesso il codice di test che lo utilizzava era ordini di grandezza più complicati del codice che stava testando. Allora ho cercato di influenzare i team in cui ero in uso con parsimonia e accontentarmi di semplici derisioni artigianali che erano semplicemente implementazioni alternative di interfacce specifiche per i test.

Recentemente le mie forti opinioni su questo argomento sono diventate più morbide poiché le API beffe hanno reso i test che li utilizzano più leggibili. In sostanza, voglio che il mio codice (compresi i test) sia modificabile da altri sviluppatori senza farli sentire come se stessero setacciando attraverso un mucchio di oscure chiamate API.

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.