Passare da finto a oggetti reali?

1

Sono come fare il TDD, così ho iniziato tutto prendendo in giro oggetti, creando interfacce, stub, grandiosi.

Il design sembra funzionare, ora implementerò le cose, molto del codice usato negli stub verrà riutilizzato nella mia reale implementazione yay!

Ora dovrei duplicare i test per utilizzare l'implementazione dell'oggetto reale (ma mantenere l'oggetto mock delle cose sensibili come Database e "servizi" che sono fuori dal mio contesto (chiamate http, ecc ...)) o semplicemente cambiare i mock e gli stub dei test reali per usare gli oggetti reali .......

Quindi la domanda è: mantenere due test o sostituire gli stub, mock?

E dopo, dovrei continuare a progettare con i mock, gli stub o semplicemente andare con oggetti reali?

(Mi sto solo rendendo chiaro che terrò l'oggetto finto delle cose sensibili come database e servizi che sono fuori dal mio contesto, in entrambe le situazioni.)

Modifica

[Fact]
public void Change_status()
{
    var dbContext = MockRepository.GenerateStub<IDbContext>();
    var repository = MockRepository.GenerateMock<IRepository<Foo>>();

    var predicate = MockRepository.GenerateStub<Func<Foo, bool>>();
    repository.Expect(x => x.Get(predicate)).Return(_foo).Repeat.Once();
    dbContext.Expect(x => x.Commit());

    var ctl = MockRepository.GenerateStub<IFooCtl>();
    ctl.Stub(x => x.RejectRequest(_fooView)).WhenCalled(delegate
    {
        var foo = repository.Get(predicate);
        foo.Status = Status.Rejected;
        _fooView.Status = Status.Rejected.ToString();

    }).Return(true);

    ctl.RejectRequest(_fooView);

    repository.VerifyAllExpectations();
    dbContext.VerifyAllExpectations();
    Assert.True(_fooView.Status == "Rejected");
    Assert.True(result.Count() == 1);
}

Questo è un test, in cui prendo in giro il repository, il contesto e la facciata. Quindi quello che sto cercando di dire è se dovessi cambiare lo stub della facciata per usare il codice "reale", quindi questo dovrebbe essere testato come

[Fact]
public void Change_status()
{
    var dbContext = MockRepository.GenerateStub<IDbContext>();
    var repository = MockRepository.GenerateMock<IRepository<Foo>>();

    var predicate = MockRepository.GenerateStub<Func<Foo, bool>>();
    repository.Expect(x => x.Get(predicate)).Return(_foo).Repeat.Once();
    dbContext.Expect(x => x.Commit());

    var ctl = new FooCtl(loanRepository, happyLoanDbContext);
    var result = ctl.RejectRequest(_loanView);

    repository.VerifyAllExpectations();
    dbContext.VerifyAllExpectations();
    Assert.True(_result);
}

O se dovessi lasciare tutto ciò che deride e lo stub che mette alla prova i progetti e ne crea di nuovi che testano l'implementazione.

Modifica

Grazie per tutta la tua risposta, penso di capirlo meglio, devo sapere qual è il mio SUT e testare che, nessun finto o stub del SUT solo i componenti che aiuteranno il SUT a superare il test

    
posta jjchiw 26.06.2012 - 00:08
fonte

4 risposte

8

Or if I should leave everything mocking and stubbing that tests the designs and create new ones that tests the implementation.

Un test unitario non verifica mai le astrazioni, o progetta come lo metti tu. Verifica sempre l'implementazione concreta one , quella della classe sotto test.

In altre parole, se hai un dispositivo di prova per la classe A in cui prendi in giro o stub fuori le dipendenze di A e C, allora non stai testando il comportamento o la progettazione di B e C. Stai solo testando il comportamento di A e che è in grado di parlare correttamente con B e C. Per testare le implementazioni concrete di B e C, devi creare fix di test dedicati per entrambi.

Da una prospettiva di test unitario puramente isolata, non è necessario sostituire i mock per implementazioni reali in seguito, né creare controparti di test di integrazione oltre ai test delle unità (test di integrazione = test che coinvolgono diverse implementazioni concrete allo stesso tempo). I test delle unità isolate dovrebbero rimanere come sono, con tutti i mock e gli stub. Stanno da soli a condizione di testare tutte le implementazioni concrete e le loro interazioni con le loro dipendenze.

Come sottolinea Erik, potrebbe creare test di integrazione, ma tieni presente che hanno un costo, sia in termini di tempi di elaborazione che di tempi di manutenzione, e non devono sostituire i test unitari come imbraco di prova principale IMO.

    
risposta data 26.06.2012 - 10:15
fonte
7

Mi sembra che tu stia chiedendo se dovresti trasformare i tuoi test unitari in test di integrazione. Direi che la risposta è decisamente no. Penso che saresti ben servito per mantenere i test unitari che stai scrivendo (quelli che usano oggetti finti) come la spina dorsale della tua suite di test.

Per i test di integrazione (in cui si assemblano parti più grandi della propria applicazione con oggetti reali invece di mock), avrei meno di questi, dal momento che sono necessariamente più dispendiosi in termini di tempo da eseguire e molto più coinvolti da mantenere. Questi sono spesso buoni come "test del fumo", ma non vorrei che fossero il fulcro della tua suite di test.

    
risposta data 26.06.2012 - 01:26
fonte
4

L'idea di TDD è che ti concentri sull'implementazione di una sola cosa alla volta. Quindi, quando si implementa una classe, si scopre di aver bisogno di una classe esterna, non si dovrebbe iniziare a implementarla, ma semplicemente creare uno stub o anche solo un'interfaccia, con funzionalità sufficienti a rendere funzionante la classe che si sta implementando.

I mazzi sono usati per essere sicuri di testare solo una cosa. Solo una lezione Quindi, anche se hai implementato delle vere e proprie classi al posto degli stub / interfaccia che hai fatto per coprire temporaneamente alcune funzionalità mancanti, i simulatori dovrebbero sempre essere lì per testare quella classe in isolamento (parte della tua suite di test automatica). Quando passi ad implementare una vera e propria classe invece dello stub, dovresti anche creare un oggetto fittizio per rappresentare la classe che hai iniziato ad implementare.

Spero che ti aiuti.

    
risposta data 26.06.2012 - 01:05
fonte
2

Le tue "vere" classi potrebbero sembrare mocciose ora, ma in futuro potrebbero cambiare drasticamente. Vuoi davvero che i futuri cambiamenti nelle tue vere classi abbiano un effetto su altri test unitari? Ne dubito. Scrivi classi di simulazione per test unitari e classi reali per codice reale, e se capita di apparire uguali, va bene.

    
risposta data 26.06.2012 - 14:00
fonte

Leggi altre domande sui tag