ChevCast
ChevCast

Reputation: 59213

How to create a Moq provider for Ninject?

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.

Upvotes: 8

Views: 2298

Answers (2)

s3raph86
s3raph86

Reputation: 566

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.

Upvotes: 0

Ian Davis
Ian Davis

Reputation: 3868

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

Upvotes: 8

Related Questions