2013-03-12 7 views
22

Se è necessario impostare un valore restituito, nonché verificare quante volte è stata richiamata l'espressione, è possibile farlo in un'unica istruzione?Moq - È possibile specificare in un programma di installazione i criteri di verifica (ad esempio tempi di chiamata)?

Da quello che posso raccogliere, l'installazione di Moq (SomeExpression) .Verifiable() chiamata insieme a Verify(), fondamentalmente fa una verifica (SomeExpression, Times.AtLeastOnce)? cioè, verifica che l'espressione fosse chiamata solo.

Ecco un esempio per spiegare meglio la domanda. Per un'interfaccia:

interface IFoo 
{ 
    int ReturnSomething(); 
} 

sono le seguenti due blocchi equivalenti (diverso dal primo verificherà tutte le impostazioni contrassegnati come verificabile)?

void Test() 
{ 
    var mock = new Mock<IFoo>(); 
    mock.Setup((m) => m.ReturnSomething()).Returns(1).Verifiable(); 

    mock.Verify(); 
} 

e

void Test() 
{ 
    var mock = new Mock<IFoo>(); 
    mock.Setup((m) => m.ReturnSomething()).Returns(1); 

    mock.Verify((m) => m.ReturnSomething(), Times.AtLeastOnce()); 
} 

Se avessi voluto verificare il numero di chiamate (diciamo due volte), è questo l'unico modo in cui l'espressione viene ripetuta per la configurazione e verificare?

void Test() 
{ 
    var mock = new Mock<IFoo>(); 
    mock.Setup((m) => m.ReturnSomething()).Returns(1); 

    mock.Verify((m) => m.ReturnSomething(), Times.Exactly(2)); 
} 

Semplicemente non mi piace dover chiamare l'installazione e verificare. Bene, poiché questa è una buona idea per AAA, per riformulare, non mi piace dover ripetere l'espressione per l'installazione e la verifica. Al momento memorizzo l'espressione in una variabile e la passo a ciascun metodo, ma non mi sento così pulito.

PS - Il contesto per questo è per una verifica di prova quando una cache è aggiornato o meno (scadenze, ecc)

+0

Questo è l'utilizzo di Moq 4 (ho visto vecchi frammenti di codice dove ci sono metodi su ISetup come AtMostOnce) – GregS

risposta

10

Per rispondere alla prima domanda, sì i due blocchi sono equivalenti. Entrambi falliranno quando viene chiamato .Verify se non è stato chiamato il metodo sul mock.

Non è possibile specificare la verifica in primo piano per quanto ne so e se ci si pensa, è logico.

Questa è specificare il comportamento del finto:

mock.Setup(m => m.ReturnSomething()).Returns(1); 

Questo sta verificando il comportamento del chiamante:

mock.Verify(m => m.ReturnSomething(), Times.AtLeastOnce()); 

Personalmente preferisco chiamare verificare individualmente per confermare il comportamento richiesto del chiamante , .Verifiable() e .Verify() sono scorciatoie che sono meno rigide (controllano solo che il metodo sia stato chiamato una o più volte) tuttavia se si sa che il proprio codice dovrebbe chiamare un metodo solo una volta, inserire la verifica alla fine per confermarlo.

Ho iniziato a farlo dopo che l'unione di codice ha provocato il richiamo di un metodo due volte, il test è stato comunque inoltrato poiché è stato chiamato almeno una volta, ma ha anche significato che qualcosa altro è accaduto più volte e non dovrebbe avere!

+0

Questo è un peccato, considerando che Rhino Mocks supporta l'installazione e verifica in una singola istruzione. Penserei che questo sarebbe uno dei casi d'uso più comuni (se non il più comune), quindi sono sconcertato di come questo non sia incluso nel framework, anche adesso, più di tre anni dopo. Immagino che passerò a Rhino Mocks ... –

10

Ho questo problema tutto il tempo. Io uso i mock rigorosi e voglio specificarlo rigorosamente (ad esempio, ho usato It.Is<>() anziché It.IsAny()) e ho verificato rigorosamente (ad esempio specificando gli orari). Non è possibile utilizzare questo parametro per verificarlo, perché a Moq manca un sovraccarico di Verifiable(Times).

L'espressione completa della chiamata, incluso It.Is<>(), è generalmente di grandi dimensioni.Quindi, al fine di evitare la duplicazione Io in genere ricorrere al seguente:

Expression<Action<MockedType>> expression = mockedTypeInstance => mockedTypeInstance.MockedMethod(It.Is<TFirstArgument>(firstArgument => <some complex statement>)/*, ...*/); 
_mock.Setup(expression); 

/* run the test*/ 

_mock.Verify(expression, Times.Once); 

Non estremamente leggibile, ma non credo che ci sia un altro modo per entrambi utilizzano impostazione rigorosa e la verifica rigorosa.

+0

L'uso di un'espressione separata da riutilizzare si adatta bene a ciò di cui ho bisogno. Bella soluzione! –

Problemi correlati