2010-10-25 10 views
5

Sto facendo delle aspettative ordinate nei burloni di rinoceronte come descritto da ayende nel numero this. Il mio codice simile a questa:Riutilizzo di un simulato verificato

using (_mocks.Ordered()) 
    { 
    Expect.Call(() => _myMock.CallA()); 
    Expect.Call(() => _myMock.CallB(40)); 
    Expect.Call(() => _myMock.CallA()); 
    } 
    _mocks.ReplayAll(); 
    _myObjectUnderTest.DoStuff(); 
    _mocks.VerifyAll(); 

Dopo questo vorrei aggiungere più aspettative e testare più dei metodi di mio oggetto. Voglio farlo perché ho alcuni metodi di test di base che eseguono alcune impostazioni sul mio oggetto test e non voglio dover ripetere il test di questa funzionalità, quindi chiamo semplicemente il metodo di test precedente. Se provo ad aggiungere più aspettative dopo VerifyAll() ottengo un'eccezione: "Questa azione non è valida quando l'oggetto fittizio è in stato verificato."

Parte del mio problema è che non capisco veramente cosa stiano facendo tutte le cose di riesame/verifica, ho appena copiato il codice. Sto usando i mock rigorosi, quindi qualsiasi codice di setup deve avere aspettative corrispondenti o fallisce. Non voglio duplicare le aspettative per il mio codice di configurazione.

C'è un modo per reimpostare il mock in modo che sia pronto per ricominciare da capo?

risposta

4

Risposta breve: no. Ora avanti alla lunga risposta.

Quello che fanno le cose di riproduzione e verifica è questo. Prima di chiamare ReplayAll, stai dicendo a Rhino cosa ti aspetti che i metodi facciano. In un certo senso, stai registrando le chiamate agli oggetti finti che hai creato.

Dopo aver registrato le chiamate di metodo, si chiama ReplayAll dicendo a Rhino che ora si sta per fare 'qualcosa' che dovrebbe eseguire i metodi come registrati.

Infine, si chiama VerifyAll chiedendo a Rhino di verificare se i metodi sono stati effettivamente chiamati così come li hai registrati.

Ora sul perché non si dovrebbe davvero voler riutilizzare i mock. Con il test dell'unità/TDD, il test dell'unità dovrebbe testare il meno possibile. Questo per mantenere i tuoi test unitari semplici e trasparenti. L'intera idea dei test unitari è che molti molti numerosi test testano l'intero sistema.

Per un'ottima presentazione su TDD che spiega questo e altri argomenti, vedere http://www.infoq.com/presentations/integration-tests-scam.

PS: Un piccolo dettaglio: Finché i metodi non restituiscono un risultato, è possibile scrivere:

using (_mocks.Ordered()) 
{ 
    Expect.Call(() => _myMock.CallA()); 
    Expect.Call(() => _myMock.CallB(40)); 
    Expect.Call(() => _myMock.CallA()); 
} 

come:

using (_mocks.Ordered()) 
{ 
    _myMock.CallA(); 
    _myMock.CallB(40); 
    _myMock.CallA()); 
} 

(almeno con la versione più recente di Rhino)

+0

Il problema si presenta quando voglio testare B, ma A deve essere chiamato per impostare dapprima tutto per B. Se A chiama i metodi sulla mia simulazione, allora devo aspettarmi che usino mock dinamici invece di quelli stretti. Non vorrei duplicare tutte le aspettative, perché ho già provato a fondo A. – captncraig

+1

Sì, ho anche questo problema. Hai due opzioni. Il primo consiste nel modificare la logica aziendale in modo da poter controllare le parti attivate o dividere la logica aziendale in parti più piccole da testare in modo indipendente.La seconda opzione è di sollevare alcune aspettative in un metodo privato del tuo '[TestFixture]' e chiamarlo in entrambi i test. Ho fatto l'ultimo (per ora). –

+0

-1 come ho avuto questo problema, ma ho trovato un modo per aggirare questo che nega questa risposta (vedi altro post - "risposta breve: sì") – brewmanz

0

risposta breve: sì

Longer risposta: Prova il seguente

[Test] 
    public void RhinoMock_PerformMultipleChecks() 
    { 
     var myMock = MockRepository.GenerateDynamicMockWithRemoting<IComparable>(); 

     // first round of checks 
     myMock.Expect(x => x.CompareTo("123")).Return(1); 
     myMock.Expect(x => x.CompareTo("-12")).Return(-1); 
     Assert.AreEqual(1, myMock.CompareTo("123")); 
     Assert.AreEqual(-1, myMock.CompareTo("-12")); 
     myMock.VerifyAllExpectations(); 

     // reset 
     myMock.BackToRecord(); 
     myMock.Replay(); 

     // next round of checks 
     myMock.Expect(x => x.CompareTo(1.23)).Return(1); 
     myMock.Expect(x => x.CompareTo(-12)).Return(-1); 
     Assert.AreEqual(1, myMock.CompareTo(1.23)); 
     Assert.AreEqual(-1, myMock.CompareTo(-12)); 
     myMock.VerifyAllExpectations(); 

     // reset 
     myMock.BackToRecord(); 
     myMock.Replay(); 

     // final round of checks 
     myMock.Expect(x => x.CompareTo(1.23m)).Return(1); 
     myMock.Expect(x => x.CompareTo(-12m)).Return(-111); 
     Assert.AreEqual(1, myMock.CompareTo(1.23m)); 
     Assert.AreEqual(-111, myMock.CompareTo(-12m)); 
     myMock.VerifyAllExpectations(); 
    }