问题描述
我正尝试在自动化测试中使用Castle Windsor,例如:
I am attempting to use Castle Windsor in my automated tests like so:
在每次测试中:
-
Setup()
函数创建一个Windsor容器,注册每个组件的默认实现 -
Test
函数通过方法IWindsorContainer.Resolve< T>
访问组件,并测试其行为 -
TearDown()
函数处理温莎容器(以及任何已创建的组件)
- The
Setup()
function creates a Windsor container, registering default implementations of each component - The
Test
function access the components via the methodIWindsorContainer.Resolve<T>
, and tests their behavior - The
TearDown()
function disposes of the Windsor container (and any created components)
例如,我可能有15个测试可以访问组件,这些测试间接地导致创建 IMediaPlayerProxyFactory
组件。 SetUp
函数注册了一个足够好的实现 IMediaPlayerProxyFactory
,所以我没有在此注册的维护负担。 15个测试中的每一个。
For example, I might have 15 tests which accesses components which indirectly results in the creation of an IMediaPlayerProxyFactory
component. The SetUp
function registers a good-enough implementation IMediaPlayerProxyFactory
, so I don't have the maintenance burden of registering this in each of the 15 tests.
但是,我现在正在编写一个测试 Test_MediaPlayerProxyFactoryThrowsException
,确认我的系统能够优雅地处理 IMediaPlayerProxyFactory
组件出现错误。在测试方法中,我创建了特殊的模拟实现,现在我想将其注入到框架中:
However, I'm now writing a test Test_MediaPlayerProxyFactoryThrowsException
, confirming my system elegantly handles an error from the IMediaPlayerProxyFactory
component. In the test method I've created my special mock implementation, and now I want to inject it into the framework:
this.WindsorContainer.Register(
Component.For<IMediaPlayerProxyFactory>()
.Instance(mockMediaPlayerProxyFactory)
);
但是温莎抛出了 Castle.MicroKernel.ComponentRegistrationException
,并显示消息已经有一个具有该名称的组件。
But Windsor throws a Castle.MicroKernel.ComponentRegistrationException
, with the message "There is already a component with that name."
有什么方法可以使我的 mockMediaPlayerProxyFactory
是 IMediaPlayerProxyFactory
的默认实例,丢弃已注册的组件吗?
Is there any way that I can make my mockMediaPlayerProxyFactory
be the default instance for the IMediaPlayerProxyFactory
, discarding the component that's already registered?
根据,温莎城堡3允许注册覆盖,但我只能找到一个示例:
According to the documentation, Castle Windsor 3 allows for registration overrides, but I could only find one example:
Container.Register(
Classes.FromThisAssembly()
.BasedOn<IEmptyService>()
.WithService.Base()
.ConfigureFor<EmptyServiceA>(c => c.IsDefault()));
ConfigureFor
是 BasedOnDescriptor
类。就我而言,我没有使用 FromDescriptor
或 BasedOnDescriptor
。
ConfigureFor
is a method of the BasedOnDescriptor
class. In my case I'm not using the FromDescriptor
or BasedOnDescriptor
.
推荐答案
创建覆盖实例必须做两件事:
There are two things that you have to do to create an overriding instance:
- 为其分配一个唯一名称
- 调用
IsDefault
方法
- Assign it a unique name
- Call the
IsDefault
method
因此,使示例生效:
this.WindsorContainer.Register(
Component.For<IMediaPlayerProxyFactory>()
.Instance(mockMediaPlayerProxyFactory)
.IsDefault()
.Named("OverridingFactory")
);
由于我计划在许多测试中使用此主要模板,因此我创建了自己的扩展方法:
Because I plan to use this overriding patten in many tests, I've created my own extension method:
public static class TestWindsorExtensions
{
public static ComponentRegistration<T> OverridesExistingRegistration<T>(this ComponentRegistration<T> componentRegistration) where T : class
{
return componentRegistration
.Named(Guid.NewGuid().ToString())
.IsDefault();
}
}
现在,示例可以简化为:
Now the example can be simplified to:
this.WindsorContainer.Register(
Component.For<IMediaPlayerProxyFactory>()
.Instance(mockMediaPlayerProxyFactory)
.OverridesExistingRegistration()
);
稍后编辑
版本3.1引入了 IsFallback
方法。如果我使用 IsFallback
注册所有初始组件,则任何新注册都会自动覆盖这些初始注册。如果当时该功能可用,我会走那条路。
Version 3.1 introduces the IsFallback
method. If I register all my initial components with IsFallback
, then any new registrations will automatically override these initial registrations. I would have gone down that path if the functionality was available at the time.
这篇关于在Castle Windsor 3中,在单元测试中覆盖现有的组件注册的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!