Ninject ActivationException: Error activating IAlertManagement
Asked Answered
S

3

9

I'm getting the following error:

Test method: BootStrapperTest.Can_Create_Alert_Management_Object threw exception:  Ninject.ActivationException: 
Error activating IAlertManagement No matching bindings are available, and the type is not self-bindable. 

Activation path:   
1) Request for IAlertManagement

Suggestions:    
1) Ensure that you have defined a binding for IAlertManagement.    
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.    
3) Ensure you have not accidentally created more than one kernel.    
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.    
5) If you are using automatic module loading, ensure the search path and filters are correct.

Here is the test case that is causing this exception:

[TestInitialize]
public void Initialize()
{
    BootStrapper.RegisterTypes();
}

[TestMethod]
public void Can_Create_Alert_Management_Object()
{
    IAlertManagement alertManagementService = BootStrapper.Kernel.Get<IAlertManagement>();

    Assert.IsNotNull(alertManagementService);
}

//This is the code that gets called in [TestInitialize]
public static void RegisterTypes()
{
    if (!initialized)
    {
        Kernel.Bind(scanner => scanner.FromAssembliesMatching("MyCompany.MyProduct.*")
                                   .SelectAllClasses()
                                   .BindDefaultInterface());

        Kernel.Unbind(typeof(IWcfServiceClient<>));
        Kernel.Bind(typeof(IWcfServiceClient<>)).ToMethod(ctx =>
                    (ctx.Kernel.Get(typeof(WcfServiceClientProvider<>).MakeGenericType(ctx.GenericArguments)) as IProvider).Create(ctx)); 
    }

    initialized = true;
}

The above error is occurring in one of my unit tests on our build server but not on my development machine. I have 7 other tests almost identical to this one that pass on the build server and on my development machine but this is the only test that fails.

The IAlertManagement interface is coming from a dll called Core and the concrete type is coming from another dll called AlertManagement. I have both the Core dll and the AlertManagement dll included in my unit test project as project references. I have 7 or 8 other tests identical to this situation but this is the only one failing.

Any ideas would be appreciative.

Selfloading answered 8/8, 2012 at 12:13 Comment(0)
S
1

I ended up resolving this by adding concrete references to the resolving types in my unit testing project. Just adding project references is not enough. This is how I'm doing this:

[TestClass]
public class AssemblyInitialize
{
    /// <summary>
    /// Method which gets executed once per unit test session. The purpose of this method is to reference any loosely coupled
    /// assemblies so that they get included in the unit test session. If no code actually references a given assembly, even if its
    /// technically a project reference, it will not be copied to the test output folder.
    /// </summary>
    [AssemblyInitialize]
    public static void InitializeReferencedAssemblies(TestContext context)
    {
        List<Type> looselyCoupledTypes = new List<Type>
                                         {
                                             typeof(AlertManagement),
                                             typeof(Naming),
                                         };

        looselyCoupledTypes.ForEach(x => Console.WriteLine("Including loosely coupled assembly: {0}",
                                                           x.Assembly.FullName));
    }
}
Selfloading answered 29/1, 2016 at 22:13 Comment(0)
B
1

The error occur because IAlertManagement is not binded with any concrete class. Try to manually bind IAlertManagement.

public static void RegisterTypes()
{
    if (!initialized)
    {
        Kernel.Bind(scanner => scanner.FromAssembliesMatching("MyCompany.MyProduct.*")
                               .SelectAllClasses()
                               .BindDefaultInterface());


        //Try to add following line
        Kernel.Bind<IAlertManagement>().To<ConcreteImplementationOfIAlertManagement>();

        Kernel.Unbind(typeof(IWcfServiceClient<>));
        Kernel.Bind(typeof(IWcfServiceClient<>)).ToMethod(ctx => (ctx.Kernel.Get(typeof(WcfServiceClientProvider<>).MakeGenericType(ctx.GenericArguments)) as IProvider).Create(ctx)); 
    }

    initialized = true;
}
Bunche answered 20/9, 2012 at 5:41 Comment(1)
That may work but this is what I wanted to get away from in the first place. I do not want to add references to all the dlls with the concrete classes.Selfloading
S
1

I ended up resolving this by adding concrete references to the resolving types in my unit testing project. Just adding project references is not enough. This is how I'm doing this:

[TestClass]
public class AssemblyInitialize
{
    /// <summary>
    /// Method which gets executed once per unit test session. The purpose of this method is to reference any loosely coupled
    /// assemblies so that they get included in the unit test session. If no code actually references a given assembly, even if its
    /// technically a project reference, it will not be copied to the test output folder.
    /// </summary>
    [AssemblyInitialize]
    public static void InitializeReferencedAssemblies(TestContext context)
    {
        List<Type> looselyCoupledTypes = new List<Type>
                                         {
                                             typeof(AlertManagement),
                                             typeof(Naming),
                                         };

        looselyCoupledTypes.ForEach(x => Console.WriteLine("Including loosely coupled assembly: {0}",
                                                           x.Assembly.FullName));
    }
}
Selfloading answered 29/1, 2016 at 22:13 Comment(0)
A
0
  1. The first thing that I would check is to ensure that the DLL that contains the implementation of IAlertManagement is getting copied to the proper directory on the build server so that the tests see it.

  2. Another thing to try would be to move the kernel loading code to a ClassInitialize function instead of a TestInitialize, just to see if there is some sort of race condition or other related thing. I've seen random errors on build servers due to objects being disposed in a different order or sooner than would normally happen (involved Rx, TPL, and unobserved exceptions in my case). It may be that more tests are run in parallel on the build server than on the desktop.

  3. Or it could be due partially to the fact that the server may be using Server GC. I don't know if forcing it to use Workstation GC would help or not but it might be worth a try.

Alliterate answered 18/9, 2012 at 20:14 Comment(2)
I do see the dll containing IAlertManagement in the drop folder on the build server. I also tried switching the unit test class to use [ClassInitialize] instead of [TestInitialize] but it didn't seem to help. I have not explored option 3.Selfloading
Just for testing, try putting the concrete AlertManagement in an assembly that you know is being seen, like Core. Just add a stub of the class for example. Then you'd know if it just can't find the file or there is something else.Alliterate

© 2022 - 2024 — McMap. All rights reserved.