hasdrubal
hasdrubal

Reputation: 1148

MockingKernel Named Multi-Bindings as constructor argument

So let's say I have an interface with two implementations

public interface IWeapon
{
    string Hit(string target);
}

public class Sword : IWeapon 
{
    public string Hit(string target) 
    {
        return "Slice " + target + " in half";
    }
}

public class Dagger : IWeapon 
{
    public string Hit(string target) 
    {
        return "Stab " + target + " to death";
    }
}

I have an object that accepts a Sword and a Dagger. I use Named multi bindings as described in the docs.

public class Samurai: ISamurai
{
    private readonly IWeapon sword;
    private readonly IWeapon dagger;

    public Samurai(
        [Named(nameof(Sword))] IWeapon sword,
        [Named(nameof(Dagger))] IWeapon dagger)
    {
        this.sword = sword;
        this.dagger = dagger;
    }
}

This works fine when I use it with normal binding in run-time case:

DependencyInjector.Kernel.Bind<IWeapon>().To<Sword>().Named(nameof(Sword));
DependencyInjector.Kernel.Bind<IWeapon>().To<Dagger>().Named(nameof(Dagger));

This doesn't work when I use mocking kernel:

Mock<IWeapon> mockSword = new Mock<IWeapon>();
Mock<IWeapon> mockDagger = new Mock<IWeapon>();

MockingKernel.Rebind<IWeapon>().ToConstant(mockSword.Object).Named(nameof(Sword));
MockingKernel.Rebind<IWeapon>().ToConstant(mockDagger.Object).Named(nameof(Dagger));

MockingKernel.Get<Samurai>();

I get the following type of error:

Message: OneTimeSetUp: Ninject.ActivationException : Error activating 
IWeapon
No matching bindings are available, and the type is not self-bindable.
Activation path:
  2) Injection of dependency IWeapon into parameter             
sword of constructor of type ISamurai
  1) Request for ISamurai

Upvotes: 1

Views: 85

Answers (1)

Jan Muncinsky
Jan Muncinsky

Reputation: 4408

Problem with Rebind<IWeapon>() method is that it removes all the bindings based on IWeapon even if you later specify Named syntax. This means that the second rebind call eliminates the first one. So try this instead:

MockingKernel.Rebind<IWeapon>().ToConstant(mockSword.Object).Named(nameof(Sword));
MockingKernel.Bind<IWeapon>().ToConstant(mockDagger.Object).Named(nameof(Dagger));

Upvotes: 1

Related Questions