Come faccio a testare l'unità con un metodo privato che viene chiamato in un ciclo come questo? [duplicare]

0

Come faccio a verificare l'unità con un metodo privato che viene chiamato in un ciclo come questo:

    // Calls MethodToUnitTest in a loop
    public static string Generate(params int[] values)
    {
        if (values.Any(i => i == 0)) // return empty string if any value contains 0 
            return "";

        return string.Join(", ", values.Select(MethodToUnitTest)); // return a comma delimited string
    }

    // Called multiple times by Generate
    private static string MethodToUnitTest(int value)
    {
        if (value % 2 == 0)
            return "Divisible by 2";

        if (value % 3 == 0)
            return "Divisible by 3";

        return value.ToString();
    }

Posso vedere due opzioni:

  1. Cambia la visibilità di MethodToUnitTest in public (e possibilmente spostalo in un'altra classe) quindi scrivi i codici di test unitario che lo esercitano.

    Con: l'output di MethodToUnitTest è solo per Generate , quindi non è necessario renderlo pubblico o spostarlo in un'altra classe. Inoltre, MethodToUnitTest è solo una semplice funzione.

  2. Prova MethodToUnitTest chiamando Generate : Contro: Semplicemente innaturale.

Sample tests

Assert.AreEqual("Divisible by 2", Generate(2));

Assert.AreEqual("Divisible by 3", Generate(3));

Assert.AreEqual("Divisible by 2, Divisible by 3", Generate(2, 3));

// ...etc

Quale soluzione è migliore? A che punto dividi un metodo in più metodi testabili individualmente?

    
posta UnitTestingN00b 25.10.2017 - 11:47
fonte

2 risposte

8

Lascia che ti risparmi un sacco di mal di testa lungo la strada: evita di testare metodi privati . Ci sono diversi motivi per questo, tra cui:

  • Implementazione fragile
  • Fare il minimo cambiamento rompe molti test unitari
  • Blocco della tua implementazione per paura di tutte le rilavorazioni che devi fare

Pensa a cosa è importante per funzionare correttamente. Quali sono le interfacce e i contratti che queste interfacce impongono o implicano. Questo è ciò che gli sviluppatori useranno. Da un punto di vista più filosofico, pensalo in questo modo:

  • L'utente della classe dovrebbe preoccuparsi se esiste un metodo privato chiamato MethodToUnitTest ? Non fa parte di alcuna interfaccia che possono utilizzare.
  • L'implementatore della classe dovrebbe essere libero di cambiare drasticamente l'implementazione mentre ancora supporta l'interfaccia esposta? Assolutamente, questo è in pratica il Principio di sostituzione di Liskov (anche se tecnicamente si tratta di sostituire le intere classi).
  • Se qualcuno che mantiene questa classe deve cambiare 3-4 test unitari perché l'implementazione interna deve cambiare? Ora stai solo creando lavoro.

La soluzione è testare solo l'interfaccia o i metodi che i consumatori di quella classe dovrebbero utilizzare. Metti alla prova i contratti di quell'interfaccia in modo da essere sicuro che funzioni bene. Aggiungi test unitari man mano che cambiano i requisiti. Se lo fai, sarai sulla buona strada per avere un'infrastruttura di test che funzioni per te invece che contro di te.

Se insisti a testare metodi privati, prevedo che tutti quei test saranno commentati, disabilitati o semplicemente rimossi entro un anno (supponendo che tu non abbia abbandonato del tutto il progetto).

    
risposta data 25.10.2017 - 14:54
fonte
0

How do I go about unit testing a private method

Non lo fai!

Unittest verifica comportamento osservabile pubblico (dove "pubblico" non implica public visibilità dell'interfaccia testata ...) che è valori di ritorno e < em> comunicazione con dipendenze .

I can see two options:

Un'altra opzione è quella di spostare quel metodo in una classe separata che diventa una dipendenza del codice sotto test e potrebbe essere sostituita con una simulazione su cui è possibile verificare le chiamate di questo metodo.

At what point do you break down a method into multiple individually testable methods?

Questo si riduce alla domanda Che cos'è un'unità? Mi piace la risposta di Roy Osherove in The Art of Unittesting :

A Unit is all the code that has the same reason to change.

Quindi un metodo privato diventa una "unità" quando sembra avere il proprio "contesto" che in qualche modo differisce dal contesto se gli altri metodi.

Un altro motivo per renderlo un'unità separata è che è difficile da testare.

    
risposta data 25.10.2017 - 12:02
fonte

Leggi altre domande sui tag