开发者

Ninject and dynamic WithConstructor/WithMeta and RhinoMocks

开发者 https://www.devze.com 2023-04-07 10:56 出处:网络
In my project I have an IoC container that gets initialized the usual way with a ServiceModule. When I write unit tests, I want to be able to bind to either a StrictMock, DynamicMock, PartialMock or S

In my project I have an IoC container that gets initialized the usual way with a ServiceModule. When I write unit tests, I want to be able to bind to either a StrictMock, DynamicMock, PartialMock or Stub. In the past I had a FakeServiceModule that would bind everything to StrictMocks, but this is very restrictive, and I wanted to expand this to allow creating a mock type of my choosing.

To achieve this I created the following.

public class NinjectMocking
{
    public Type TypeToMock { get; set; }
    public MockType MockTypeToUse { get; set; }
    public IBindingWithOrOnSyntax<Type> BindingWithOrOnSyntax { get; set; }   
}

public enum MockType
{
    Stub,
    Strict,
    Dynamic,
    Partial
}开发者_Go百科

The idea is that I would initialise the fake service module like so:

        foreach (var mockType in _mocks)
        {
            object ninjaMock;

            switch (mockType.MockTypeToUse)
            {
                case MockType.Strict:
                    {
                        ninjaMock = _mockRepository.StrictMock(mockType.TypeToMock);
                        break;
                    }
                case MockType.Dynamic:
                    {
                        ninjaMock = _mockRepository.DynamicMock(mockType.TypeToMock);
                        break;
                    }
                case MockType.Partial:
                    {
                        ninjaMock = _mockRepository.PartialMock(mockType.TypeToMock);
                        break;
                    }
                case MockType.Stub:
                    {
                        ninjaMock = _mockRepository.Stub(mockType.TypeToMock);
                        break;
                    }
                default:
                    {
                        ninjaMock = _mockRepository.StrictMock(mockType.TypeToMock);
                        break;
                    }
            }

            if (mockType.BindingWithOrOnSyntax == typeof(ConstructorArgument))
                Bind(mockType.TypeToMock).ToMethod(m => ninjaMock).w
                    .WithConstructorArgument(mockType.BindingWithOrOnSyntax);

            else
                Bind(mockType.TypeToMock).ToMethod(m => ninjaMock);
        }

Having been initliazed with a list of mocks...

       NinjectMocking ninjectMocking = new NinjectMocking();
        ninjectMocking.TypeToMock = typeToAdd;
        ninjectMocking.MockTypeToUse = MockType.Dynamic;

This all works perfectly. However, and here comes the question, some of our bindings need either .WithConstructorArgument or .WithMetaData as in

        Bind<ISomeRepository>().ToMethod(m => someRepository)
        .WithConstructorArgument("context", ctx => new TestDataContext());

and maybe some others in the future. That is why I have the BindingWithOrOnSyntax property in the NinjectMocking class. So my new initializer may look something like this:

        NinjectMocking ninjectMocking = new NinjectMocking();
        ninjectMocking.TypeToMock = typeToAdd;
        ninjectMocking.MockTypeToUse = MockType.Dynamic;
        ninjectMocking.BindingWithOrOnSyntax.WithConstructorArgument("context", constructorArgument);

The problem is I don't know how to make it use that in the binding. What I would like to do is something like

Bind(mockType.TypeToMock).ToMethod(m => ninjaMock).[WhatGoesHere]

I don't really know how to do it with the [WhatGoesHere] bit, or how else to define the Bind so that it uses whatever I pass in, in the BindingWithOrOnSyntax property. My last desperate attempt was to try force it via something like

            if (mockType.BindingWithOrOnSyntax == typeof(ConstructorArgument))
                Bind(mockType.TypeToMock).ToMethod(m => ninjaMock)
                    .WithConstructorArgument(mockType.BindingWithOrOnSyntax);

But that obviously doesn't work.

Any pointers in the right direction, or even if there is a better way to achieve this, would be greatly appreciated.


Don't use an IOC container during unit testing. An IOC container is to be used at runtime to inject your dependencies into your components. During unit testing, you create your components with mocked/stubbed dependencies. If your components are resolving dependencies directly from the IOC container, you're not using the container properly.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号