Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ninject ToFactory works in Resharper unit tests, but not NCrunch

I'm using Ninject.Extensions.Factory with Ninject 3 to create a factory, which creates different types of IFoo based on the string provided to the factory. I've got a passing unit test, but oddly, only in the Resharper test runner. In the NCrunch test runner it fails. Is this a NCrunch config issue, or do I need to change the code?

The interface:

public interface IFooFactory
{
    IFoo CreateFoo(string name);
}

The Ninject bindings:

kernel.Bind<IFooFactory>().ToFactory(() => new UseFirstParameterAsNameInstanceProvider());
kernel.Bind<IFoo>().To<BarFoo>().Named("Bar");

The test:

[Test]
public void CanCreateFooTest()
{
    var factory = (IFooFactory) Kernel.GetService(typeof(IFooFactory));
    var bar = factory.CreateFoo("Bar");
    Assert.AreEqual(typeof(BarFoo), bar.GetType());
}

And the NCrunch exception:

System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> Ninject.ActivationException : Error activating IInterceptor using conditional implicit self-binding of IInterceptor
Provider returned null.
Activation path:
  2) Injection of dependency IInterceptor into parameter  of constructor of type IFooFactoryProxy
  1) Request for IFooFactory

Suggestions:
  1) Ensure that the provider handles creation requests properly.

   at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Ninject.Infrastructure.Language.ExtensionsForIEnumerable.ToArraySlow(IEnumerable series, Type elementType) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerable.cs:line 29
   at Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:line 149
   at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 114
   at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.<Create>b__2(ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 96
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Ninject.Activation.Providers.StandardProvider.Create(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:line 95
   at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 157
   at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at Ninject.KernelBase.System.IServiceProvider.GetService(Type service) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 553
   at FooProject.Tests.CanCreateFooTest() in C:\Projects\FooProject ...
--ActivationException
   at Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:line 165
   at Ninject.KernelBase.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:line 386
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
like image 652
harriyott Avatar asked May 15 '12 12:05

harriyott


3 Answers

Go into the NCrunch configuration for the unit test library and set Copy referenced assemblies to workspace to True.

NCrunch confuguration screenshot

like image 95
shamp00 Avatar answered Oct 20 '22 12:10

shamp00


Here the code that works with NCrunch:

        var kernel = new StandardKernel();
        kernel.Bind<IFooFactory>().ToFactory(() => new UseFirstParameterAsNameInstanceProvider());
        kernel.Bind<IFoo>().To<BarFoo>().Named("Bar");
        kernel.Load<FuncModule>();

        var factory = kernel.Get<IFooFactory>();
        var bar = factory.CreateFoo("Bar");
        Assert.Equal(typeof(BarFoo), bar.GetType());

UPDATE

This works great, and sorts out NCrunch. However, Resharper complains that it has been loaded twice. The workaround:

    #if NCRUNCH
        Kernel.Load<FuncModule>(); 
    #endif
like image 38
the_joric Avatar answered Oct 20 '22 12:10

the_joric


The FuncModule is not loaded when running with that TestRunner. This happens in case the extension is not copied to the startup directory of the executed process.

I don't NCrunch. So I can't tell you what it is doing. But most likely it copies the assemblies in a different way than the R# test runner. You could load the extensions manually but this feels like a hack.

like image 32
Remo Gloor Avatar answered Oct 20 '22 12:10

Remo Gloor