In Castle Windsor 3, override an existing component registration in a unit test

I am attempting to use Castle Windsor in my automated tests like so:

On every test:

  • The Setup() function creates a Windsor container, registering default implementations of each component
  • The Test function access the components via the method IWindsorContainer.Resolve<T> , and tests their behavior
  • The TearDown() function disposes of the Windsor container (and any created components)
  • 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.

    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)
                                  );
    

    But Windsor throws a Castle.MicroKernel.ComponentRegistrationException , with the message "There is already a component with that name."

    Is there any way that I can make my mockMediaPlayerProxyFactory be the default instance for the IMediaPlayerProxyFactory , discarding the component that's already registered?


    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 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:

  • Assign it a unique name
  • Call the IsDefault method
  • So to get the example to work:

    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()
                              );
    


    Later Edit

    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.

    https://github.com/castleproject/Windsor/blob/master/docs/whats-new-3.1.md#fallback-components


    Don't reuse your container across tests. Instead, set it to null in the TearDown() and re-initialise it for each actual test.

    链接地址: http://www.djcxy.com/p/59866.html

    上一篇: 温莎城堡组装版本和MSTest

    下一篇: 在Castle Windsor 3中,覆盖单元测试中现有的组件注册