¿Cómo simulo la dependencia de fábrica Func para devolver diferentes objetos utilizando AutoMock?
Estoy intentando escribir una prueba para una clase que depende del constructor en una Func<T>
. Para que la función de prueba se complete con éxito, necesita crear varios objetos separados de tipo T
.
Cuando se ejecuta en producción, AutoFac genera un nuevo T
cada vez que se llama a factory()
. Sin embargo, al escribir una prueba usando AutoMock, devuelve el mismo objeto cuando se llama de nuevo.
El caso de prueba a continuación muestra la diferencia en el comportamiento al usar AutoFac y AutoMock. Esperaría que ambos pasen, pero el de AutoMock falla.
public class TestClass
{
private readonly Func<TestDep> factory;
public TestClass(Func<TestDep> factory)
{
this.factory = factory;
}
public TestDep Get()
{
return factory();
}
}
public class TestDep
{}
[TestMethod()]
public void TestIt()
{
using var autoMock = AutoMock.GetStrict();
var testClass = autoMock.Create<TestClass>();
var obj1 = testClass.Get();
var obj2 = testClass.Get();
Assert.AreNotEqual(obj1, obj2);
}
[TestMethod()]
public void TestIt2()
{
var builder = new ContainerBuilder();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
var testClass = container.Resolve<TestClass>();
var obj1 = testClass.Get();
var obj2 = testClass.Get();
Assert.AreNotEqual(obj1, obj2);
}
davy.ai
El problema con la prueba que utiliza AutoMock falla porque AutoMock devuelve el mismo objeto cuando se llama
factory()
. Esto es porque AutoMock está diseñado para ser utilizado en pruebas unitarias y cachea instancias de dependencias para mejorar la velocidad de la prueba y reducir el uso de memoria. Sin embargo, esto puede crear problemas al probar clases que tienen dependencias enFunc<t>
, ya que la función necesita generar un nuevo objeto del tipoT
cada vez que se llama.Para solucionar este problema, se puede crear un
Func<t>
personalizado que devuelva una nueva instancia deT
cada vez que se llame. Aquí hay un ejemplo:En la primera prueba, creamos una fábrica personalizada que devuelve una nueva instancia de
TestDep
cada vez que se llama. Luego, reemplazamos la instancia deFunc<testdep>
en el contenedor de AutoMock con la fábrica personalizada antes de crear la instancia deTestClass
. Esto asegura queGet()
genere una nueva instancia deTestDep
cada vez que se llama.En la segunda prueba, registramos
TestDep
yTestClass
con el contenedor AutoFac. Usamos el métodoWithParameter
para inyectar unFunc<testdep>
personalizado que resuelveTestDep
del contenedor cada vez que se llama. Nuevamente, esto asegura queGet()
genere una nueva instancia deTestDep
cada vez que se llama.