unit-testing - software - pruebas unitarias laravel
En Castle Windsor 3, anular un registro de componente existente en una prueba de unidad (2)
Estoy tratando de usar Castle Windsor en mis pruebas automatizadas de la siguiente manera:
En cada prueba:
- La función
Setup()
crea un contenedor Windsor, registrando implementaciones predeterminadas de cada componente - La función de
Test
accede a los componentes a través del métodoIWindsorContainer.Resolve<T>
y prueba su comportamiento - La función
TearDown()
elimina el contenedor de Windsor (y cualquier componente creado)
Por ejemplo, podría tener 15 pruebas que accedan a componentes, lo que indirectamente resulta en la creación de un componente IMediaPlayerProxyFactory
. La función SetUp
registra una implementación suficientemente buena IMediaPlayerProxyFactory
, por lo que no tengo la carga de mantenimiento de registrar esto en cada una de las 15 pruebas.
Sin embargo, ahora estoy escribiendo una prueba Test_MediaPlayerProxyFactoryThrowsException
, confirmando que mi sistema maneja con elegancia un error del componente IMediaPlayerProxyFactory
. En el método de prueba, he creado mi implementación simulada especial, y ahora quiero insertarla en el marco:
this.WindsorContainer.Register(
Component.For<IMediaPlayerProxyFactory>()
.Instance(mockMediaPlayerProxyFactory)
);
Pero Windsor lanza una Castle.MicroKernel.ComponentRegistrationException
, con el mensaje "Ya existe un componente con ese nombre".
¿Hay alguna manera de hacer que mockMediaPlayerProxyFactory
sea la instancia predeterminada para IMediaPlayerProxyFactory
, descartando el componente que ya está registrado?
Container.Register(
Classes.FromThisAssembly()
.BasedOn<IEmptyService>()
.WithService.Base()
.ConfigureFor<EmptyServiceA>(c => c.IsDefault()));
ConfigureFor
es un método de la clase BasedOnDescriptor
. En mi caso no estoy usando el FromDescriptor
o BasedOnDescriptor
.
Hay dos cosas que debes hacer para crear una instancia de reemplazo:
- Asígnele un nombre único
- Llame al método
IsDefault
Así que para que el ejemplo funcione:
this.WindsorContainer.Register(
Component.For<IMediaPlayerProxyFactory>()
.Instance(mockMediaPlayerProxyFactory)
.IsDefault()
.Named("OverridingFactory")
);
Debido a que planeo usar este patrón de reemplazo en muchas pruebas, he creado mi propio método de extensión:
public static class TestWindsorExtensions
{
public static ComponentRegistration<T> OverridesExistingRegistration<T>(this ComponentRegistration<T> componentRegistration) where T : class
{
return componentRegistration
.Named(Guid.NewGuid().ToString())
.IsDefault();
}
}
Ahora el ejemplo se puede simplificar para:
this.WindsorContainer.Register(
Component.For<IMediaPlayerProxyFactory>()
.Instance(mockMediaPlayerProxyFactory)
.OverridesExistingRegistration()
);
Edición posterior
La versión 3.1 introduce el método IsFallback
. Si registro todos mis componentes iniciales con IsFallback
, cualquier nuevo registro anulará automáticamente estos registros iniciales. Hubiera seguido ese camino si la funcionalidad estuviera disponible en ese momento.
https://github.com/castleproject/Windsor/blob/master/docs/whats-new-3.1.md#fallback-components
No reutilice su envase a través de pruebas. En su lugar, TearDown()
en null
en TearDown()
y TearDown()
para cada prueba real.