2012-10-02 17 views
30

Voglio verificare che un metodo sul mio NSubstitute mock venga chiamato con un particolare argomento array.NSubstitute: controllo dei metodi ricevuti con gli argomenti dell'array

Dire che l'interfaccia, IProcessor, ha un metodo void ProcessSomething(Foo[] something]). Supponiamo che la mia classe sottoposta a test sia denominata Commander. Ho impostato il mio test come questo:

//prepare 
var processor = Substitute.For<IProcessor>; 
var commander = new Commander(processor); 
var foo1 = new Foo("alpha"); 
var foo2 = new Foo("bravo"); 
var foos = new [] {foo1, foo2}; 

//act 
commander.DoSomething(foo1, foo2); 

//verify 
processor.Received().ProcessSomething(foos); // FAILS 

La chiamata Received() fallisce con:

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive a call matching: 
    ProcessSomething(Foo[]) 
Actually received no matching calls. 
Received 1 non-matching call (non-matching arguments indicated with '*' characters): 
    ProcessSomething(*Foo[]*) 

Quindi questo sembra ProcessSomething è stato chiamato con una certa gamma diversa foos, giusto?

Beh, se io invece testare questo tipo, dove ho catturare il valore dell'argomento usando Arg.Do(), ci riesce:

//prepare 
//... as before 
var actualFoos = null; 

processor.ProcessSomething(Arg.Do<Foo[]>(x => actualFoos = x)); 

//act 
commander.DoSomething(foo1, foo2); 

//verify 
Assert.That(actualFoos, Is.EqualTo(foos)); // SUCCEEDS 

Quindi catturare la discussione e il confronto per l'uguaglianza (con NUnit in questo esempio) funziona, ma la verifica della chiamata ricevuta non riesce.

Si tratta di un errore in NSubstitute o sto usando male?

risposta

36

Suppongo che l'oggetto Commander prenda gli argomenti e li inserisca in un array che utilizza per chiamare il modello Processor.

La variabile foos è un altro array creato durante l'installazione. Gli array non si confrontano l'uno con l'altro anche se hanno gli stessi elementi. Quindi NSubstitute si lamenterà che non ha ricevuto il valore atteso (ha ricevuto un altro array che ha contenuto gli stessi elementi).

Edit: Prova questa versione:

//prepare 
var processor = Substitute.For<IProcessor>; 
var commander = new Commander(processor); 
var foo1 = new Foo("alpha"); 
var foo2 = new Foo("bravo"); 
var foos = new [] {foo1, foo2}; 

//act 
commander.DoSomething(foo1, foo2); 

//verify 
processor.Received().ProcessSomething(Arg.Is<Foo[]>(foos2 => foos.SequenceEqual(foos2)); 

Ciò richiede l'importazione del namespace System.Linq

+1

Dopo aver letto la tua risposta, ho guardato nella fonte NUnit, e ho visto che Is.EqualTo (via EqualConstraint) controlla le raccolte per l'uguaglianza confrontando gli elementi nelle raccolte. Ecco perché catturare il valore e il controllo ha funzionato. Ora la domanda è, perché le collezioni .Net non implementano Equals, ma questo è un problema per un altro giorno. – Jimothy

+0

Questa è una bella sintassi. Molto più pulito di RhinoMocks –

Problemi correlati