2009-04-20 14 views
57

Vorrei impostare un valore di ritornoCome cancellare le aspettative precedenti su un oggetto?

_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(true); 

ma poi in un test specifico, ignorare questa aspettativa per restituire false.

Qualcosa di simile:

_stubRepository.ClearExpectations(); //<- this does not exist, I'm just making something up 
_stubRepository.Stub(Contains(null)).IgnoreArguments().Return(false); 

Avviso, non voglio l'aspettativa per tornare falso in seconda convocazione, voglio ignorare la prima aspettativa.

Ciò contribuirebbe a semplificare notevolmente il mio scenario di test.

risposta

67

ci sono tre modi:

È possibile ripristinare le aspettative utilizzando BackToRecord

devo ammettere che non ho mai usato davvero perché è imbarazzante.

// clear expectations, an enum defines which 
_stubRepository.BackToRecord(BackToRecordOptions.All); 
// go to replay again. 
_stubRepository.Replay(); 

Edit: Ora lo uso a volte, è in realtà il modo più pulito. Ci dovrebbe essere un metodo di estensione (come Stub) che lo fa - penso che sia appena stato dimenticato. Suggerirei di scrivere il tuo.

È possibile utilizzare Repeat.Any()

E 'rompe' l'ordine della definizione stubbed e "override" definizioni precedenti. Ma è in qualche modo implicito. Lo uso a volte perché è facile da scrivere.

_stubRepository.Stub(x => x.Contains(null)) 
    .IgnoreArguments() 
    .Return(false) 
    .Repeat.Any(); 

È possibile creare un nuovo finto

banale, ma esplicito e facile da capire. È solo un problema se vuoi mantenere molte definizioni e cambiare solo una chiamata.

_stubRepository = MockRepository.GenerateMock<IRepository>(); 
_stubRepository.Stub(x => x.Contains(null)) 
    .IgnoreArguments() 
    .Return(false); 
+0

In Rhino Mock interno parlare usando Repeat. Qualsiasi crea un'aspettativa ripetibile, che supera le normali aspettative durante la riproduzione. Raccomando comunque di usare BackToRecord. –

+0

Ah, ho capito tutto tranne la chiamata a Replay(). –

+1

Questa è una cosa conosciuta solo da persone che usano RhinoMocks dalla versione 3.4 o precedente. RhinoMocks ha funzionato con Record-Replay, questo significa che un mock doveva essere impostato in modo replay in modo esplicito. Con 3.5, fortunatamente questo è andato, i mock sono sempre in modalità replay (almeno per il codice personalizzato). Fino a quando non lo rimandi alla modalità di registrazione - a parte le aspettative di cancellazione, non vedo alcun motivo per farlo. Volevo già scrivere una patch per queste due righe per reimpostare comodamente le aspettative. –

22

Per queste situazioni, ho creato un metodo semplice estensione RinoMocks per mostrare meglio l'intento dello stub e promuovere la leggibilità.

public static void OverridePrevious<T>(this IMethodOptions<T> options) 
{ 
    options.Repeat.Any(); 
} 

Così, invece di una chiamata criptico come la seguente che può richiedere un commento:

[SetUp] 
public void Setup() 
{ 
    carStub.Stub(x => x.Model).Return("Model1"); 
    carStub.Stub(x => x.Model).Return("Model2"); 
} 

[Test] 
public void SomeTest() 
{ 
    //Arrange 
    //overrides previous stubs that were setup for the Model property 
    carStub.Stub(x => x.Model).Return(null).Repeat.Any(); 

    //Act 
    //Assert 
} 

è possibile ottenere un test più leggibile che meglio mostra l'intento del .Repeat.Any() chiama :

carStub.Stub(x => x.Model).Return(null).OverridePrevious(); 
+5

Per mantenere l'opzione aperta per concatenare la configurazione dello stub, il metodo di estensione non dovrebbe restituire un IMethodOptions ? 'public static IMethodOptions OverridePrevious (this IMethodOptions options) {return options.Repeat.Any(); } '. – PHeiberg

+2

@PHeiberg - Non l'ho provato o ho avuto bisogno di tenere la "catena aperta" ma sì, suppongo che tu abbia ragione. Buon punto – MoMo

+0

Mi piace OverridePrevious come vuoto - lo costringe alla fine. – user2864740

5

per il bene della comunità aggiungerò questo da aggiungere alla lista delle opzioni di cui sopra di Stefan:

Se il valore di ritorno deve essere cambiato frequentemente, trovo pulito ed efficiente usare una chiusura come segue.

bool returnValue = true; 
_stubRepository.Stub(x => x.Contains(null)).IgnoreArguments().Do(new Func<bool>(() => { 
    return returnValue; 
})); 

returnValue = false; 
// Calls to Contains now return false; 

returnValue = true; 
// Calls to Contains now return true; 

L'espressione lambda verrà eseguito ogni volta che viene chiamato Contains e perché abbiamo creato una chiusura riferimento returnValue, sarà sempre cercare il valore corrente di returnValue.

+0

Questa è la soluzione più pulita a mio parere –

Problemi correlati