Mocking Extension Methods com Moq

Eu tenho uma interface preexistente …

public interface ISomeInterface { void SomeMethod(); } 

e eu estendi este intreface usando um mixin …

 public static class SomeInterfaceExtensions { public static void AnotherMethod(this ISomeInterface someInterface) { // Implementation here } } 

Eu tenho uma class 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 onde 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(); someInterfaceMock.Setup(x => x.AnotherMethod()).Verifiable(); var caller = new Caller(someInterfaceMock.Object); // Act caller.Main(); // Assert someInterfaceMock.Verify(); } 

Executar este teste, no entanto, gera uma exceção …

 System.ArgumentException: Invalid setup on a non-member method: x => x.AnotherMethod() 

A minha pergunta é, há uma maneira legal de ridicularizar a chamada do mixin?

Você não pode “diretamente” simular o método estático (daí o método de extensão) com a estrutura de simulação. Você pode tentar 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:

Moles é uma estrutura leve para stubs de teste e desvios no .NET que é baseada em delegates.

As Moles podem ser usadas para desviar qualquer método .NET, incluindo methods não virtuais / estáticos em tipos selados.

Você pode usar Moles com qualquer framework de teste (independente disso).

Eu usei um Wrapper para contornar este problema. Crie um object de invólucro e passe seu método de simulação.

Veja Mocking Static Methods for Unit Testing por Paul Irwin, ele tem bons exemplos.

Descobri que precisava descobrir o interior do método de extensão para o qual eu estava tentando imitar a input e simular o que estava acontecendo dentro da extensão.

Eu vi usando uma extensão como adicionar código diretamente ao seu método. Isso significa que eu precisava zombar do que acontece dentro da extensão em vez da própria extensão.

Eu gosto de usar o wrapper (padrão de adaptador) quando estou envolvendo o próprio object. Não tenho certeza se usaria isso para envolver um método de extensão, que não faz parte do object.

Eu uso uma propriedade injetável interna preguiçosa de qualquer tipo de ação, Func, predicado ou delegado e permitem injetar (trocar) o método durante um teste de unidade.

  internal Func DoWorkMethod { [ExcludeFromCodeCoverage] get { return _DoWorkMethod ?? (_DoWorkMethod = (obj, val) => { return obj.DoWork(val); }); } set { _DoWorkMethod = value; } } private Func _DoWorkMethod; 

Então você chama o Func em vez do método atual.

  public object SomeFunction() { var val = "doesn't matter for this example"; return DoWorkMethod.Invoke(MyObjectProperty, val); } 

Para um exemplo mais completo, confira http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/