Come vengono comunemente utilizzati gli oggetti finti?

15

Ho letto recentemente un articolo in cui si diceva che gli oggetti finti sono spesso fraintesi e mal utilizzati. Esistono degli anti-schemi di derisione chiari che posso cercare?

    
posta Armand 10.06.2011 - 12:05
fonte

5 risposte

13

Detesto vedere semplici classi concrete derise. Ad esempio, prendi la seguente classe semplice 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 uno di quelli reali fosse istanziato e usato piuttosto che un'interfaccia come "IPerson", una beffa usata e le aspettative impostate su. Usando quello reale il tuo test è più realistico (hai i parametri di verifica in atto e la reale implementazione della proprietà 'Name'). Per una classe semplice come questa non stai facendo i tuoi test più lenti, meno deterministici o infangando la logica (non è probabile che tu abbia bisogno di sapere che Nome è stato chiamato quando collaudi un'altra classe) - che sono le solite ragioni per deridere / stubbing.

Come estensione a questo ho anche visto persone scrivere test in cui la simulazione è impostata con un'aspettativa, quindi la simulazione viene chiamata direttamente nel test. Insolitamente il test passerà sempre ... hmmmm ...

    
risposta data 10.06.2011 - 12:43
fonte
10

Potrebbe sembrare ovvio, ma: non utilizzare oggetti finti nel codice di produzione! Ho visto più di un esempio in cui il codice di produzione dipendeva dalle caratteristiche di determinati oggetti mock ( MockHttpServletRequest da Springframework per esempio).

    
risposta data 10.06.2011 - 12:11
fonte
9

Secondo me è il controllo eccessivo del metodo di chiamata sui mock. Ritengo che questa sia una pratica applicata da alcuni framework di simulazione come EasyMock, in cui il comportamento predefinito di mock è fallire ogni volta che c'è un richiamo di un metodo aggiuntivo rispetto a ciò che non era esattamente specificato prima. Questo tipo di rigoroso controllo del metodo simulato può portare a progetti fragili in cui il più piccolo cambiamento al codice può portare a un'intera suite di test che non riescono, anche se la funzionalità di base è sempre la stessa.

Una soluzione a questo sta iniziando a usare stub invece di mock. Un articolo che ho trovato particolarmente illuminante sull'argomento è stato trovato in Javadoc di Mockito: link (vedi "2. Che ne dici di alcuni stub?"), che collega a: link .

Mi è piaciuto lavorare con Mockito finora perché non impone questo rigido comportamento di derisione ma l'uso di stub. Impone anche il controllo del metodo su quelli specifici invece dell'intero oggetto fittizio; così finisci per controllare solo i metodi che contano davvero nello scenario di test.

Ci sono alcuni libri qua e là che posso consigliare di toccare questo argomento e di prendere in giro e in generale:

xModifica di unità

The Art of Unit Testing: con esempi in .Net

Test Java di prossima generazione: TestNG e Advanced Concepts (questo libro riguarda principalmente testNG, ma c'è un bel capitolo sulla simulazione)

    
risposta data 10.06.2011 - 19:13
fonte
4

Ho osservato alcuni anti-pattern nella mia esperienza.

  • Classi di dominio che vengono derise / stubbate in cui può verificarsi un cambiamento di stato e che deve essere verificato.
  • Test di integrazione che interagiscono con un mix di mock e classi concrete che sconfigge lo scopo dei test di integrazione.
  • Uso involontario di mock nel codice di produzione (Questo non dovrebbe mai accadere)

Altrimenti la mia esperienza con i mock soprattutto Mockito è stata un gioco da ragazzi. Hanno reso i test molto facili da scrivere e mantenere. Il test dell'interazione GWT / presentatore è molto più semplice con i mock rispetto a GWTTestCase.

    
risposta data 11.06.2011 - 08:30
fonte
2

Trovo che i test che utilizzano i mock 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 di framework mock migliorate (io uso JMock dove conveniente).

5 o 6 anni fa API come EasyMock erano potenti ma molto ingombranti. Spesso il codice di prova che ne faceva uso era di ordine di grandezza più complicato del codice che stava testando. Allora ho cercato di influenzare i team in cui mi trovavo per usarlo con parsimonia e accontentarmi di semplici mock artigianali che erano semplicemente implementazioni alternative di interfacce specifiche per i test.

Recentemente le mie forti opinioni su questo argomento sono diventate più sfumate mentre le API di simulazione hanno reso più leggibili i test che li utilizzano. Essenzialmente voglio che il mio codice (compresi i test) sia intercambiabile da altri sviluppatori senza farli sentire come se stessero setacciando una melodia di oscure chiamate API.

    
risposta data 10.06.2011 - 12:33
fonte