2010-10-19 14 views
8

Sono nuovo di TDD e DDD e ho una semplice domanda riguardante i metodi statici in generale. La maggior parte dei guru di TDD dice in una parola che i metodi statici sono cattivi (e che dovremmo dimenticare di creare tonnellate di utility statiche che noi (um o I) usavamo prima perché non sono testabili. non testabile (un ottimo articolo di chiarimento può essere trovato here per coloro che sono interessati ma suppongo di essere l'unico noob qui :() ma mi chiedevo ci fosse una linea guida bella e pulita per usare la statica dal punto di vista TDD?Metodi statici: quando e quando no

Questa potrebbe essere una domanda stupida per molti di voi, ma alcuni suggerimenti sarebbero grandiosi e voglio solo sapere come gli esperti qui pensano a cose statiche Grazie in anticipo

Modifica: Mentre cercavo risposta ho trovato 2 altri belle discussioni riguardo l'uso di statica (non preoccupazione TDD però) che io Indovina sono buone letture per coloro che sono interessati (me compreso).

risposta

11

penso che si può avere un po 'frainteso.

I metodi statici sono testabili. Prendete questo metodo come un esempio:

public static int Add(int x, int y) 
{ 
    return x + y; 
} 

È possibile verificare questo testando che il valore di ritorno è quello che ci si aspetta sulla base degli argomenti passati in

Dove metodi statici diventa fastidioso quando il test è quando è necessario. introdurre una finta.

Diciamo che ho un codice che chiama il metodo statico File.Delete(). Per testare il mio codice senza fare affidamento sul file system, vorrei sostituire/prendere in giro questa chiamata con una versione di test che verifica solo che sia stata chiamata dal codice in fase di test. Questo è facile da fare se avessi un'istanza di un oggetto su cui è stato chiamato Delete(). La maggior parte dei framework di simulazione (tutti?) Non possono prendere in giro metodi statici, quindi l'uso di un metodo statico nel mio codice mi costringe a verificarlo in modo diverso (di solito chiamando il metodo statico reale).

Per provare qualcosa di simile a questo, vorrei introdurre un'interfaccia:

interface IFileDeleter 
{ 
    void Delete(string file); 
} 

Il mio codice sarebbe poi prendere un'istanza di un oggetto che implementa questa interfaccia (sia nella chiamata di metodo o come parametro nel costruttore), e quindi chiamare il suo metodo Delete() a fare la cancellazione:

void MyMethod(string file) 
{ 
    // do whatever... 
    deleter.Delete(file); 
} 

per verificare ciò, posso fare una finta dell'interfaccia IFileDeleter e semplicemente verificare che il suo metodo Delete() era stato chiamato. Ciò elimina la necessità di avere un vero file system come parte del test.

Questo può sembrare che il codice sia più complesso (che è), ma si ripaga da solo nel rendere molto più facile da testare.

+0

+1! Typemock può prendere in giro metodi statici, ma è meglio evitarli (quando dovranno essere derisi). – TrueWill

+0

+1 grazie heap per una risposta completa. Aspetterò solo poche altre risposte (se ce ne sono) prima di selezionare una risposta per il gusto di condividere la conoscenza – MSI

+0

Hm quello che ho chiesto è stato davvero un po 'sciocco ora che ho letto la tua risposta. sì, hai ragione, mi sono perso il punto in cui ho posto la domanda. Sta beffandosi quando sorgono dei veri problemi; non testare il metodo stesso specialmente quando è solo un metodo di utilità. – MSI

7

In generale, se il metodo:

  • è lento
  • è lunga
  • contiene la logica complessa
  • utilizza il file system
  • connette a un database
  • Chiama una web servizio

quindi evitare di renderlo statico. (Vedi la risposta di @adrianbanks per un'eccellente discussione sulle ragioni alla base di questa e delle alternative.)

Fondamentalmente, è sufficiente renderlo statico se è un metodo di memoria breve in memoria (come molti metodi di estensione).

+0

Mi piace molto la tua risposta. Ha senso, prendi il colpo di testare la logica dello statico come parte del SUT, per la convenienza che l'utilità Static ti porta, se e solo se non ha nessuno dei tratti che hai scritto. Quindi, dato un metodo veloce, semplice, privo di effetti collaterali, metodo statico, si presuppone che sia una primitiva, un'estensione della tua lingua, e basta usarlo nelle tue unità senza isolamento. –

8

Evitare la statica è certamente la strada da percorrere, ma quando non è possibile o si sta lavorando con il codice Legacy, è disponibile la seguente opzione. Sulla scia di adrianbanks risposta precedente, diciamo che ha il seguente codice (scuse, la sua in Java come non so C#):

public void someMethod() { 
    //do somethings 
    File.delete(); 
    //do some more things 
} 

è possibile refactoring del File.Delete() nel proprio metodo come questo:

public void someMethod() { 
    //do somethings 
    deleteFile(); 
    //do some more things 
} 

//protected allows you to override in a subclass 
protected void deleteFile() { 
    File.delete(); 
} 

e poi in preparazione per il test di unità creare una classe finta che si estende quello originale e stub che la funzionalità:

//Keep all the original functionality, but stub out the file delete functionality to 
//prevent it from using the real thing and while you're at it, keep a record that the 
//method was called. 
public class MockClass extends TheRealClass { 
    boolean fileDeleteCalled = false; 

    @Override 
    protected void deleteFile() 
     //don't actually delete the file, 
     //just record that the method to do so was called 
     fileDeleteCalled = true; 
    } 

    public boolean fileDeleteCalled() { 
     return fileDeleteCalled; 
    } 
} 

e, infine, nel vostro unit test:

//This would normally be instantiated in the @Before method 
private MockClass unitUnderTest = new MockClass(); 

@Test 
public void testFileGetsDeleted(){ 
    assertFalse(unitUnderTest.fileDeleteCalled()); 
    unitUnderTest.someMethod(); 
    assertTrue(unitUnderTest.fileDeleteCalled()); 
} 

Ora che hai eseguito tutte le funzionalità di someMethod() senza in realtà eliminare il file, e avete ancora la possibilità di vedere se questo metodo è stato chiamato.

+0

+1 per la grande idea. Grazie amico – MSI

+0

qualcuno gli dia più voti per favore per il bell'esempio e il chiarimento – MSI

Problemi correlati