1

I am testing a class that has two dependencies on IFoo. Both instances of IFoo should be MOCK objects so that I can VerifyExpectations on each. Each instance is created and managed by the RhinoMocksMockingKernel.

I think that the mocking kernel is getting confused about which instance it should be verifying.

I also think that I may be confused about the proper way to setup RhinoMocksMockingKernel for this case.

I do know that I can use dep1.AssertWasCalled... vs. dep1.VerifyAllExpectations().

Here is the sample code.

public interface IFoo
{
    void DoX();
    void DoY();
}

public class SubjectUnderTest
{

    private readonly IFoo dep1;
    private readonly IFoo dep2;

    public void DoWork()
    {
        dep1.DoX();
        dep2.DoY();
    }

    public SubjectUnderTest(IFoo dep1, IFoo dep2)
    {
        this.dep2 = dep2;
        this.dep1 = dep1;            
    }
}

[TestFixture]
public class Tests
{
    [Test]
    public void DoWork_DoesX_And_DoesY()
    {
        var kernel = new Ninject.MockingKernel.RhinoMock.RhinoMocksMockingKernel();
        var dep1 = kernel.Get<IFoo>();
        var dep2 = kernel.Get<IFoo>();

        // tried this binding but it doesnt seem to work
        kernel.Bind<SubjectUnderTest>()
            .ToSelf()
            .WithConstructorArgument("dep1", dep1)
            .WithConstructorArgument("dep2", dep2);

        var sut = kernel.Get<SubjectUnderTest>();

        dep1.Expect(it => it.DoX());
        dep2.Expect(it => it.DoY());

        sut.DoWork();

        dep1.VerifyAllExpectations();
        dep2.VerifyAllExpectations();
    }
}
CedricB
  • 1,157
  • 9
  • 23
  • 1
    Why use the mocking kernel to get the SUT when you have already constructed your two dependencies. Why not just use the contructor by hand. – ryber Nov 30 '11 at 14:48
  • will manually creating the SUT fix the issue? using mocking kernel do get SUT is a common pattern when using the mocking kernel, as i can add new dependencies to the ctor w/o having to explicitly Get them. – CedricB Dec 03 '11 at 05:03
  • Best practice is not to use IOC in unit tests. You should be manually managing your dependencies in the tests. the IOC actually adds extra code and dependencies you don't need there. – ryber Dec 03 '11 at 18:11
  • whose best practices? yours? microsofts? sounds like a bold opinion. otherwise why would frameworks such as Rhino Automocking Kernel exist? Or even the TestControllerBuilder included in the MvcContrib.TestHelpers. I think we should just leave using IOC in unit tests up to preference. – CedricB Dec 09 '11 at 05:49
  • Your test would be at least half the size it is without the IOC. Read Kent Beck or Bob Martin, Both would advocate keeping the test as simple and free of external dependencies as possible. The fact is, your test does not need IOC to pass, it does not help you in any way, it's just waste. Simplify. – ryber Dec 12 '11 at 01:38

2 Answers2

2

As ryber said, you should not really be using your IOC container in your tests that way. However, I'll still answer the question in case you have this issue in normal code. You can use the Named attribute as shown in this other stackoverflow question: How To Use Ninject Named Bindings With DependencyResolver and PropertyInjection

In that example, the Named attribute is above of the function but you can also put it right next to your arguments to specify which one should be used. E.g.

public void SubjectUnderTest([Named("Alpha")] IFoo alpha, [Named("Beta")]) {
  ...
}

And the bindings should be registered as such described in this post: How To Use Ninject Named Bindings With DependencyResolver and PropertyInjection

You can also use a the ToMethod binding to just manually create your object.

Community
  • 1
  • 1
giulianob
  • 178
  • 1
  • 9
0

So I found a way to verify the expections on dep1 and dep2, but I was not able to use the AutoMockingKernel to manage and create dep1 and dep1.

Here is the code that I came up with.

It's pretty lame answer. It seems like I should be able to use the mocking kernel to Get two seperate instances of IFoo...

Here is my current code... lameo...

[TestFixture]
public class Tests
{
    [Test]
    public void DoWork_DoesX_And_DoesY()
    {
        var kernel = new Ninject.MockingKernel.RhinoMock.RhinoMocksMockingKernel();
        var dep1 = MockRepository.GenerateMock<IFoo>();
        var dep2 = MockRepository.GenerateMock<IFoo>();

        kernel.Bind<IFoo>().ToMethod((ctx) => dep1).When((ctx) => ctx.Target.Name.StartsWith("dep1"));
        kernel.Bind<IFoo>().ToMethod((ctx) => dep2).When((ctx) => ctx.Target.Name.StartsWith("dep2"));

        var sut = kernel.Get<SubjectUnderTest>();

        dep1.Expect(it => it.DoX());
        dep2.Expect(it => it.DoY());

        sut.DoWork();

        dep1.VerifyAllExpectations();
        dep2.VerifyAllExpectations();
    }
}
CedricB
  • 1,157
  • 9
  • 23