2012-01-17 6 views
6

Con Moq, è possibile verificare che un metodo sia mai chiamato con determinati argomenti (ovvero argomenti che soddisfano determinati predicati) utilizzando Times.Never.Perché non c'è un Times. Sempre in Moq?

Ma come verificare che, no mater quante volte viene chiamato un metodo, è sempre chiamato con determinati argomenti??

Il valore predefinito è Times.AtLeastOnce.

Non c'è Times.Always. Mi manca qualcosa di ovvio? Grazie!

Modifica: Ho inviato un suggerimento alla mailing list di Moq la scorsa settimana, ma non sembra che sia stato ancora moderato. Pubblicherò qualsiasi aggiornamento qui.

Modifica: un esempio. Diciamo che sto testando una classe che genera documenti XML. Voglio assicurarmi che vengano generati solo documenti validi. In altre parole, verifica che la dipendenza dello scrittore sia sempre uguale a dato i documenti validi, con un numero di sequenza valido, da scrivere.

should_only_write_valid_xml_documents 

Mock.Get(this.writer).Verify(
    w => w.Write(
     It.Is<XDocument>(doc => XsdValidator.IsValid(doc)), 
     It.Is<int>(n => n < 3)), 
    Times.Always); 
+2

"sempre" implica sapere quante volte "sempre "lo è, e se lo sapete, perché non usare invece Times (n)? – mtijn

+0

No, non è questo il punto della domanda. Immagina un metodo chiamato in un ciclo le cui dimensioni sono determinate dinamicamente. –

+0

quindi dentro l'iterazione del ciclo controllerei che il metodo sia stato chiamato una volta, ancora e ancora e ancora. questo presuppone che il ciclo sia nel codice di test. se invece è nel codice da testare, allora mi piacerebbe riprogettare la testabilità in modo da poter collegare il codice di loop per controllare ogni chiamata di metodo. – mtijn

risposta

3

Sembra che tu desideri un comportamento simulato "Stretto". Se il metodo viene chiamato con qualcosa di diverso dai parametri previsti, il test avrà esito negativo.

Questa è disponibile in Moq:

var mock = new Mock<IFoo>(MockBehavior.Strict); 

(. Esempio tratto dalla Moq QuickStart)

Ogni invocazione mock deve ora avere un corrispondente Setup.

L'utilizzo di simulazioni rigorose tende a condurre a prove fragili. Eviterei questa tecnica, o almeno la userei con parsimonia.

+1

Certo - ma se esiste, questa opzione mi consente di evitare il fastidio di passare a un rigoroso simulato e alla configurazione aggiuntiva che comporta. –

8

E quante volte è "sempre?" Moq tiene traccia di tutte le volte che un determinato metodo viene chiamato con determinati argomenti, e quindi usa quel numero per confrontarlo con Times.Never, Times.AtLeastOnce, ecc.

Quindi, se un metodo viene eseguito 4 volte e si imposta a 'Times. Sempre' cosa significa?

Times.Never verrebbe controllato per assicurarsi che il numero sia zero.

Times.AtLeastOnce controllerebbe che il numero sia maggiore o uguale a uno.

Times.Always dovrebbe controllare che il numero sia ....?

è possibile determinare il numero di volte in cui deve essere eseguita a livello di codice, quindi fare qualcosa di simile:

Times.Exactly(calculatedAmount) 

ma non c'è modo per Moq di sapere che cosa 'sempre' mezzi.

+0

Non riesco a vedere come questo possa essere vero. Moq sa cosa significa "mai" - "sempre" è l'inverso di "mai". Il numero da te menzionato verrebbe semplicemente confrontato con il numero totale di invocazioni, rispetto a zero. –

+1

@PeteMontgomery Moq sa cosa significa "mai" perché significa zero. "Sempre" è un numero ambiguo che potrebbe includere qualsiasi numero intero positivo. Volendo Moq per testare che ogni volta che viene chiamato un metodo, è stato chiamato, sembra essere un punto controverso. Se stai eseguendo l'esecuzione più volte (come in un ciclo), tieni semplicemente una variabile che rappresenta quante volte dovrebbe essere chiamata ed esegui un test che verifica su Times.Exactly (numTimesShouldRun). – docmanhattan

+0

Hmm, temo che sia in contraddizione o fraintenda il punto della domanda. Sto parlando di testare che ogni volta che viene chiamato un metodo, viene chiamato * con determinati argomenti *. Guarda le altre risposte. –

0

La mia raccomandazione sarebbe quella di creare una corrispondenza 'fallback' per il metodo con It.IsAny conditions. È quindi possibile verificare Times.Never su quella corrispondenza, che deve sempre essere sostituita dalla corrispondenza più specifica.

+0

Puoi mostrare come farlo? (Le chiamate a Verify non "falliscono" se questo è ciò che intendi - sono indipendenti per quanto posso vedere.) O vuoi dire riscrivere il test per usare Times.Never? A volte non è possibile, perché dovresti specificare tutti i possibili argomenti non validi. Saluti, Pete. –

2

È possibile applicare l'inversione della logica per verificare SEMPRE.

Esempio:

Diciamo che si desidera effettuare le seguenti operazioni di verifica:

mock.Verify(x => x.Method(It.Is<int>(i => i == 10)), Times.Always()); 

si può semplicemente sostituirlo con:

mock.Verify(x => x.Method(It.Is<int>(i => i != 10)), Times.Never()); 
+0

Ciao, la motivazione esatta per la mia domanda è che, sebbene sia possibile farlo in casi semplici, come nel tuo esempio, non puoi farlo in tutti i casi. Ad esempio: verifica che un metodo venga sempre chiamato solo con un documento XML che soddisfi determinati criteri.Non è possibile scrivere tutti i possibili documenti XML che non soddisfano tali criteri, quindi non è possibile "invertire" la verifica per utilizzare Times.Never. –

+0

Scusate, sono totalmente in errore su quest'ultimo punto: ho appena realizzato che in generale è possibile invertire e utilizzare Times.Never, a patto di testare solo un argomento alla volta. –

Problemi correlati