NSubstituto:Verificando métodos recebidos com argumentos de array
-
12-12-2019 - |
Pergunta
Quero verificar se um método em minha simulação NSubstitute é chamado com um argumento de matriz específico.
Diga a interface, IProcessor
, tem um método void ProcessSomething(Foo[] something])
.Digamos que minha classe em teste tenha um nome Commander
.Eu configurei meu teste assim:
//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
O Received()
chamada falha com:
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[]*)
Então parece que ProcessSomething foi chamado com algum array diferente de foos
, certo?
Bem, se eu testar assim, onde capturo o valor do argumento usando Arg.Do()
, ele consegue:
//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
Portanto, capturar o argumento e compará-lo quanto à igualdade (com NUnit neste exemplo) funciona, mas a verificação da chamada recebida falha.
Isso é um bug no NSubstitute ou estou usando errado?
Solução
Presumo que o seu Commander
objeto pegará os argumentos e os colocará em um array que então usará para chamar o Processor
zombar.
Seu foos
variável é outro array que você cria em sua configuração.Matrizes não são comparadas iguais entre si, mesmo que tenham os mesmos elementos.Portanto, o NSubstitute reclamará que não recebeu o valor esperado (recebeu outro array que continha os mesmos elementos).
Editar: Experimente esta versão:
//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));
Isso requer a importação do System.Linq
Espaço para nome