2012-05-15 17 views
10

Ninject.Extensions.Factory with Ninject 3を使用して、ファクトリを作成して工場に提供された文字列に基づいて異なるタイプのIFooを作成します。私は合格ユニットテストを持っていますが、奇妙なことに、Resharperテストランナーだけです。 NCrunchテストランナーでは失敗します。これはNCrunch設定の問題ですか、またはコードを変更する必要がありますか?Ninject ToFactoryはResharper単体テストで動作しますが、NCrunchでは動作しません。

インタフェース:

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

Ninjectバインディング:

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

試験:

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

そしてNCrunch例外:

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) 

答えて

6

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

これは素晴らしい作品、およびNCrunchを選別します。しかし、Resharperはそれが2度ロードされたと不平を言う。回避策:

#if NCRUNCH 
     Kernel.Load<FuncModule>(); 
    #endif 
+3

私はそれがより良いですが、NInjectまでEnsureLoadedのようなものを提供しています主張しません。 、#ifの代替案(別のアプローチをしたい場合)は、既にKernel.HasModule(typeof(FuncModule)。フルネーム)経由でロードされているかどうかを確認しています –

+0

私たちは、メインexeの組み込みリソースからのすべてのアセンブリ(ninjectを含む)。この解決策もここでは機能します(手動で 'FuncModule'を読み込みます)。私たちの場合、@ JamesManningの解決策は、すでにいくつかの場所で使われていたdllだからです。 –

4

FuncModuleは、そのTestRunnerで実行しているときに読み込まれません。これは、拡張が実行されたプロセスの起動ディレクトリにコピーされない場合に発生します。

私はNCrunchしません。だから私はそれが何をしているのかを伝えることはできません。しかし、R#テストランナーとは異なる方法でアセンブリをコピーする可能性が最も高いです。拡張機能を手動で読み込むことはできますが、これはハックのように感じます。ここで

8

は、ユニット・テスト・ライブラリのNCrunch設定に移動し、にワークスペースからコピー参照されるアセンブリを設定します。

NCrunch confuguration screenshot

+0

+1この解決法は私にとって完璧に機能しました。パフォーマンスに大きな影響があるかどうかは不明です。 –

2

私は1年かそこらのためにharriyottの提案を使用しています。しかし、この問題はTFS-Buildserverでも起こります。これで、Ninjectがすべての拡張機能を自動的にロードするのを避け、手動でロードします。これは#if#endif回避し、同じコードは、ReSharperのとNCrunch上で実行されます:

var kernel = new StandardKernel(new NinjectSettings { LoadExtensions = false}); 
kernel.Load<FuncModule>(); 

残りは変更されません:

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

var factory = kernel.Get<IFooFactory>(); 
var bar = factory.CreateFoo("Bar"); 
Assert.Equal(typeof(BarFoo), bar.GetType()); 
関連する問題