Eu tenho uma interface preexistente ...
public interface ISomeInterface
{
void SomeMethod();
}
e eu estendi essa interface usando um mixin ...
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
Eu tenho uma classe que está chamando isso que eu quero testar ...
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
e um teste em que eu gostaria de zombar da interface e verificar a chamada para o método de extensão ...
[Test]
public void Main_BasicCall_CallsAnotherMethod()
{
// Arrange
var someInterfaceMock = new Mock<ISomeInterface>();
someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable();
var caller = new Caller(someInterfaceMock.Object);
// Act
caller.Main();
// Assert
someInterfaceMock.Verify();
}
A execução deste teste, no entanto, gera uma exceção ...
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
Minha pergunta é: existe uma boa maneira de zombar da chamada de mixin?
c#
unit-testing
mocking
extension-methods
moq
Russell Giddings
fonte
fonte
Respostas:
Você não pode "diretamente" simular o método estático (portanto, o método de extensão) com a estrutura de simulação. Você pode experimentar o Moles ( http://research.microsoft.com/en-us/projects/pex/downloads.aspx ), uma ferramenta gratuita da Microsoft que implementa uma abordagem diferente. Aqui está a descrição da ferramenta:
Você pode usar Moles com qualquer estrutura de teste (é independente disso).
fonte
Eu usei um Wrapper para solucionar esse problema. Crie um objeto wrapper e passe seu método simulado.
Veja Mocking Static Methods for Unit Testing de Paul Irwin, ele tem bons exemplos.
fonte
Eu descobri que tinha que descobrir o interior do método de extensão para o qual estava tentando zombar da entrada e zombar do que estava acontecendo dentro da extensão.
Eu vi usando uma extensão como adicionar código diretamente ao seu método. Isso significava que eu precisava zombar do que acontece dentro da extensão e não da própria extensão.
fonte
Você pode simular uma interface de teste que herda da real e tem um membro com a mesma assinatura que o método de extensão.
Você pode simular a interface de teste, adicionar a real à simulação e chamar o método de teste na configuração.
Sua implementação do mock pode chamar o método desejado ou simplesmente verificar se o método é chamado:
Agradecemos à solução Håvard S neste post por saber como implementar uma simulação que suporta duas interfaces. Depois que o encontrei, adaptá-lo com a interface de teste e o método estático foi uma caminhada.
fonte
SomeNotAnExtensionMethod
eSomeNotAnExtensionMethod
? Agora eu tenho idéia de como criar uma assinatura de método de extensão dentro de uma interface ...iReal
parâmetro paraSomeExtensionMethod
no caso deITest
? Se você o passar como primeiro parâmetro, como você o instalará?Setup( x=> x.SomeExtensionMethod(x, ...)
isso causará uma exceção de tempo de execução.object _mockCache = whatever
... `Setup (x => x.SomeExtensionMethod (...) .. Callback (() => você pode acesso _mockCache aqui);)Você pode facilmente zombar de um método de extensão com o JustMock . A API é o mesmo que zombar do método normal. Considere o seguinte
Para organizar e verificar esse método, use o seguinte:
Aqui também está um link para a documentação: Métodos de extensão Mocking
fonte
Eu gosto de usar o wrapper (padrão do adaptador) quando estou quebrando o próprio objeto. Não tenho certeza se usaria isso para agrupar um método de extensão, que não faz parte do objeto.
Eu uso uma Propriedade Injectável Preguiçosa interna do tipo Action, Func, Predicate ou delegate e permito injetar (trocar) o método durante um teste de unidade.
Então você chama o Func em vez do método real.
Para um exemplo mais completo, consulte http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
fonte
Portanto, se você estiver usando o Moq e quiser zombar do resultado de um método Extension, poderá usar
SetupReturnsDefault<ReturnTypeOfExtensionMethod>(new ConcreteInstanceToReturn())
na instância da classe mock que possui o método de extensão que você está tentando zombar.Não é perfeito, mas, para fins de teste de unidade, funciona bem.
fonte