Tengo una interfaz preexistente ...
public interface ISomeInterface
{
void SomeMethod();
}
y he extendido esta interfaz usando un mixin ...
public static class SomeInterfaceExtensions
{
public static void AnotherMethod(this ISomeInterface someInterface)
{
// Implementation here
}
}
Tengo una clase que llama esto que quiero probar ...
public class Caller
{
private readonly ISomeInterface someInterface;
public Caller(ISomeInterface someInterface)
{
this.someInterface = someInterface;
}
public void Main()
{
someInterface.AnotherMethod();
}
}
y una prueba en la que me gustaría simular la interfaz y verificar la llamada al método de extensión ...
[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();
}
Sin embargo, ejecutar esta prueba genera una excepción ...
System.ArgumentException: Invalid setup on a non-member method:
x => x.AnotherMethod()
Mi pregunta es, ¿hay una buena manera de burlarse de la llamada mixin?
c#
unit-testing
mocking
extension-methods
moq
Russell Giddings
fuente
fuente
Respuestas:
No se puede "simular" directamente el método estático (de ahí el método de extensión) con el marco de imitación. Puede probar Moles ( http://research.microsoft.com/en-us/projects/pex/downloads.aspx ), una herramienta gratuita de Microsoft que implementa un enfoque diferente. Aquí está la descripción de la herramienta:
Puede usar Moles con cualquier marco de prueba (es independiente de eso).
fuente
He usado un Wrapper para solucionar este problema. Crea un objeto contenedor y pasa tu método burlado.
Vea Burlándose de métodos estáticos para pruebas unitarias por Paul Irwin, tiene buenos ejemplos.
fuente
Descubrí que tenía que descubrir el interior del método de extensión para el que intentaba burlarme de la entrada y burlarme de lo que estaba sucediendo dentro de la extensión.
Lo vi usando una extensión como agregar código directamente a su método. Esto significaba que necesitaba burlarme de lo que sucede dentro de la extensión en lugar de la extensión en sí.
fuente
Puede simular una interfaz de prueba que hereda de la real y tiene un miembro con la misma firma que el método de extensión.
Luego puede simular la interfaz de prueba, agregar la real a la simulación y llamar al método de prueba en la configuración.
Su implementación del simulacro puede llamar al método que desee o simplemente verificar que se llame al método:
Gracias a la solución Håvard S en esta publicación por cómo implementar un simulacro que admite dos interfaces. Una vez que lo encontré, adaptarlo con la interfaz de prueba y el método estático fue muy fácil.
fuente
SomeNotAnExtensionMethod
ySomeNotAnExtensionMethod
? Ahora tengo idea de cómo crear una firma de método de extensión dentro de una interfaz ...iReal
parámetro aSomeExtensionMethod
en caso deITest
? Si lo pasa como primer parámetro, ¿cómo se configura?Setup( x=> x.SomeExtensionMethod(x, ...)
Esto provocará una excepción de tiempo de ejecución.object _mockCache = whatever
... `Setup (x => x.SomeExtensionMethod (...) .. Callback (() => puede acceder _mockCache aquí);)Puede burlarse fácilmente de un método de extensión con JustMock . La API es lo mismo que burlarse del método normal. Considera lo siguiente
Para organizar y verificar este método, use lo siguiente:
Aquí también hay un enlace a la documentación: Métodos de extensión Burlándose
fuente
Me gusta usar el contenedor (patrón de adaptador) cuando estoy envolviendo el objeto en sí. No estoy seguro de usarlo para ajustar un método de extensión, que no es parte del objeto.
Utilizo una propiedad de inyección diferida interna de tipo Action, Func, Predicate o delegate y permito inyectar (intercambiar) el método durante una prueba unitaria.
Luego llama al Func en lugar del método real.
Para un ejemplo más completo, visite http://www.rhyous.com/2016/08/11/unit-testing-calls-to-complex-extension-methods/
fuente
Entonces, si está utilizando Moq y quiere burlarse del resultado de un método de Extensión, puede usar
SetupReturnsDefault<ReturnTypeOfExtensionMethod>(new ConcreteInstanceToReturn())
en la instancia de la clase simulada que tiene el método de extensión que está intentando burlarse.No es perfecto, pero para fines de pruebas unitarias funciona bien.
fuente