2010-02-12 12 views
6

Quando l'unità testa una base di codici, quali sono i segni rivelatori di cui ho bisogno per utilizzare oggetti finti?Test unitari metodi di annullamento/segni rivelatori di oggetti fittizi

Questo sarebbe semplice come vedere molte chiamate ad altri oggetti nel codebase?

Inoltre, come sono i metodi di test dell'unità che non restituiscono valori? Quindi se io restituisco un metodo void ma stampo su un file, devo semplicemente controllare il contenuto del file?

Mocking è per le dipendenze esterne, quindi è letteralmente tutto, no? File system, db, rete, ecc ...

+0

Per l'ultimo controllo del punto: http://martinfowler.com/articles/mocksArentStubs.html solo per accertarsi di essere a conoscenza delle differenze. – Finglas

+0

Ecco una buona lettura che affronta alcune di queste domande: http://xunitpatterns.com/TestStrategy.html –

risposta

2

Se mai, probabilmente uso i mock.

Ogni volta che una classe effettua una chiamata a un altro, generalmente mi prende in giro quella chiamata e verifica che la chiamata sia stata effettuata con i parametri corretti. Altrimenti, avrò un test unitario per verificare che il codice concreto dell'oggetto deriso si comporti correttamente.

Esempio:

[Test] 
public void FooMoo_callsBarBaz_whenXisGreaterThan5() 
{ 
    int TEST_DATA = 6; 
    var bar = new Mock<Bar>(); 
    bar.Setup(x => x.Baz(It.Is<int>(i == TEST_DATA))) 
     .Verifiable(); 

    var foo = new Foo(bar.Object); 

    foo.moo(TEST_DATA); 

    bar.Verify(); 
} 

... 
[Test] 
public void BarBaz_doesSomething_whenCalled() 
{ 
    // another test 
} 

La cosa per me è, se provo a testare un sacco di classi come una grande glob, quindi di solito c'è tonnellate di codice di installazione. Non solo questo è abbastanza confuso da leggere mentre cerchi di comprendere tutte le dipendenze, è molto fragile quando è necessario apportare modifiche.

Preferisco di gran lunga test succinti. Più facile da scrivere, più facile da mantenere, più facile da capire l'intento del test.

+4

Si finisce per legare il test ai dettagli di implementazione interni con mock che significano che tendono a rompersi più spesso. Con test basati sullo stato ti interessa solo un output. I mazzi sono generalmente più complicati da configurare, ma hanno sicuramente il loro posto nei test unitari. – Finglas

-1

I test unitari sono solo per un pezzo di codice che funziona autonomamente al suo interno. Ciò significa che non dipende da altri oggetti per fare il suo lavoro. È necessario utilizzare i mock se si sta eseguendo la programmazione Test-Driven o la programmazione Test-First. Dovresti creare un mock (o stub come mi piace chiamarlo) della funzione che creerai e impostare determinate condizioni perché il test passi. Originariamente la funzione restituisce false e il test fallisce, il che è previsto ... quindi si scrive il codice per fare il vero lavoro fino a quando non passa.

Ma quello che penso si riferisce a test di integrazione, non test di unità. In tal caso, dovresti usare i mock se stai aspettando che altri programmatori finiscano il loro lavoro e al momento non hai accesso alle funzioni o agli oggetti che stanno creando. Se si conosce l'interfaccia, che si spera che altrimenti si faccia beffe, è inutile e una perdita di tempo, quindi è possibile creare una versione semplificata di ciò che si spera di ottenere in futuro.

In breve, i mock si utilizzano al meglio quando si stanno aspettando gli altri e si ha bisogno di qualcosa per terminare il proprio lavoro.

Si dovrebbe cercare di restituire sempre un valore, se possibile. A volte ci si imbatte in problemi in cui si sta già restituendo qualcosa, ma in C e C++ è possibile avere parametri di output e quindi utilizzare il valore restituito per il controllo degli errori.

+0

-1 - Si basa su un fraintendimento di mock e stub. Mentre si disabilita sicuramente la funzionalità quando si esegue TDD, non è quello a cui servono gli oggetti mock. Non prendi in giro l'oggetto sotto test, prendi in giro le sue dipendenze. – TrueWill

+0

Sì, credo che ci sia una differenza tra matrici e mock. Penso che tu abbia frainteso quello che ho detto. Nel primo paragrafo stavo descrivendo quali sono stati i test unitari e come potresti utilizzare un oggetto che hai creato che simula un oggetto reale al quale non hai accesso o cui non ti interessa accedere. Nel secondo paragrafo ho iniziato a descrivere che i mock sono per i test di integrazione ... ma ho sbagliato. I test di integrazione vengono eseguiti dopo il test dell'unità e vengono eseguiti con oggetti reali e non con mock. In entrambi i casi, le mazze vengono utilizzate al meglio quando si desidera eseguire test unitari prima di integrarsi. –

0

Mazzi/tronchi/falsi/raddoppia test/ecc. vanno bene nei test unitari e consentono di testare la classe/il sistema in prova separatamente. I test di integrazione potrebbero non utilizzare nessun mock; in realtà colpiscono il database o altre dipendenze esterne.

Si utilizza un finto o uno stub quando è necessario. Generalmente questo è perché la classe che stai provando a testare ha una dipendenza da un'interfaccia. Per TDD si desidera programmare interfacce, non implementazioni e utilizzare l'iniezione delle dipendenze (in generale).

Un caso molto semplice:

public class ClassToTest 
{ 
    public ClassToTest(IDependency dependency) 
    { 
     _dependency = dependency; 
    } 

    public bool MethodToTest() 
    { 
     return _dependency.DoSomething(); 
    } 
} 

IDependency è un'interfaccia, forse uno con chiamate costose (accesso al database, chiamate di servizi Web, ecc). Un metodo di prova potrebbe contenere codice simile a:

// Arrange 

var mock = new Mock<IDependency>(); 

mock.Setup(x => x.DoSomething()).Returns(true); 

var systemUnderTest = new ClassToTest(mock.Object); 

// Act 

bool result = systemUnderTest.MethodToTest(); 

// Assert 

Assert.That(result, Is.True); 

Nota che sto facendo i test di stato (come suggerito @Finglas), e sto solo affermando contro il sistema in prova (l'istanza della classe I' m test). Potrei controllare i valori di proprietà (stato) o il valore di ritorno di un metodo, come mostra questo caso.

Si consiglia di leggere The Art of Unit Testing, soprattutto se si utilizza .NET.