Search code examples
inversion-of-controlcastle-windsorioc-containercastle

Castle.MicroKernel.ComponentNotFoundException - When Unit Testing


I am trying to unit test an Orchestrator.

//Arrange
var containter = new WindsorContainer();
var Orch = containter.Resolve<ApiOrchestrator>();// Exception Thrown here

The Constructor for the Orchestrator is:

public ApiOrchestrator(IApiWrap[] apiWraps)
{
    _apiWraps = apiWraps;
}

The registration is

public class IocContainer : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<FrmDataEntry>().LifestyleTransient());
        container.Register(Component.For<ApiOrchestrator>().LifestyleTransient());
        container.Register(Component.For<IApiWrap>().ImplementedBy<ClassA>().LifestyleTransient());
        container.Register(Component.For<IApiWrap>().ImplementedBy<ClassB>().LifestyleTransient());
    }
}

The IocContainer is in the project being tested but the namespace is referenced and I can new up an Orchestrator. I want it to just give me the array of all registered IApiWrap.

Being new to Castle I don't understand what's missing. Code fix would be nice, but I'd really like to know why the container doesn't seem to have the orchestrator registered.


Solution

  • OK so 3 things are missing

    1. A reference to Castle.Windsor.Installer
    2. A call from container to installer to 'go look for' all of the registered classes.
    3. The installer also needed to add a sub resolver to make a collection of the classes since a specific collection was not registered and a Collection of IApiWrap is required by the orchestrator.

    The Installer change

    public class IocContainer : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            //New Line
            container.Kernel.Resolver.AddSubResolver(
                      new CollectionResolver(container.Kernel, true));
    
            container.Register(Component.For<FrmDataEntry>().LifestyleTransient());
            container.Register(Component.For<ApiOrchestrator>().LifestyleTransient());
            container.Register(Component.For<IApiWrap>().ImplementedBy<SettledCurveImportCommodityPriceWrap>().LifestyleTransient());
            container.Register(Component.For<IApiWrap>().ImplementedBy<ForwardCurveImportBalmoPriceWrap>().LifestyleTransient());
        }
    }
    

    The Test / Resolving Change

    //Arrange
            var container = new WindsorContainer();
    
            //New Line
            container.Install(FromAssembly.InDirectory(new AssemblyFilter("","EkaA*") ));
    
            var Orch = container.Resolve<ApiOrchestrator>();
    

    Now it works, though any further explanation or correction of what the code is doing is welcome.