How to create a Moq provider for Ninject?
Asked Answered
E

2

8

I want to create a simple Ninject provider that returns Moq'd instances instead of concrete types. So far I have this:

public class NinjectMockProvider<T> : IProvider
{
    public static Type Type { get { return typeof(T); } }

    public object Create(IContext context)
    {
        Mock<T> newMock = new Mock<T>();
        return newMock.Object;
    }
}

But this is all wrong I'm sure as I don't know what I'm doing really. Any help and code samples would be great. I just want the ability to do:

kernel.Bind<ISomeInterface>().ToProvider<NinjectMoqProvider<ISomeInterface>>();

or something to that effect.

Update

I did figure out that I could accomplish what I want by using Ninject's method binding:

kernel.Bind<ISomeInterface>().ToMethod(x => new Mock<ISomeInterface>().Object);

I still would like a more elegant way and I may have to check out Ninject.Moq as suggested by Ian, but if anyone has any real code examples that would be awesome.

Eyewash answered 29/7, 2011 at 18:25 Comment(1)
Thx, method binding example is greatStatism
W
8

Does the MockingKernel extension handle what you need? It has Moq, RhinoMocks, and NSubstitute flavors, and it is also available on NuGet.

Wriggler answered 29/7, 2011 at 19:23 Comment(2)
I'm sure it probably does but I was looking to make my own simple wrapper just so I could understand it better.Eyewash
I would recommend looking at the source code for the extensions as it may provide some insight into mocking kernels.Wriggler
B
0

My solution to this always just uses the following:

MoqProvider

public class MoqProvider<T> : Provider<T> // T is the desired service
{
    protected override T CreateInstance(IContext context)
    {
        return new Mock<T>().Object;
    }
}

I then also register an IMissingBindingResolver with my kernel. The MoqMissingBindingResolver simply creates a new binding to a MoqProvider for any service for which a binding does not already exist.

MoqMissingBindingResolver

public class MoqMissingBindingResolver : NinjectComponent, IMissingBindingResolver
{
    public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
    {
        if (request.Service.IsAbstract || request.Service.IsInterface)
        {
            var moqProvider = (IProvider)Activator.CreateInstance(typeof(MoqProvider<>).MakeGenericType(request.Service));
            return new IBinding[] 
            { 
                new Binding(request.Service, new BindingConfiguration 
                { 
                    ProviderCallback = ctx => moqProvider,
                    ScopeCallback    = Settings.DefaultScopeCallback
                }) 
            }; 
        }
        else
        {
            return Enumerable.Empty<IBinding>();
        }
    }
}

I typically also set Settings.DefaultScopeCallback to singleton so that I can request my mocked objects in my tests later on when I need to verify certain calls have or haven't taken place, or setup behaviour on mocks prior to executing the test. So setting up my kernel will look like the following:

INinjectSettings Settings = new NinjectSettings 
{ 
    DefaultScopeCallback = StandardScopeCallbacks.Singleton    
};

var k = new StandardKernel(Settings);
k.Components.Add<IMissingBindingResolver, MoqMissingBindingResolver>();

Hope this is helpful.

Brucie answered 13/1, 2017 at 2:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.