2013-11-26 17 views
6

私が現在取り組んでいるASP.Net MVC 4アプリケーションには、ウェアハウスプロパティを持つ多くのモデルがあります。これらのモデルのすべてに、入力された倉庫が有効な倉庫であることを確認する検証が必要です。これを行う最も簡単な方法は、カスタムのValidationAttributeクラスを使用することでした。次に、検証コードが集中化され、各モデルのプロパティに属性を追加するだけで済みます。ASP.Net MVC 4カスタムValidationAttribute依存性注入

倉庫が有効な倉庫であることを確認するためにサービスを呼び出す必要があります。私はこのサービスを表すインターフェイスを持っており、このサービスが使用されているアプリケーションで依存関係注入を行うためにNinjectを使用しています。そうすれば、私は嘲笑を使用してアプリケーションで単体テストを簡単に行うことができます。

私のカスタムValidationAttributeクラスで、このサービスを使用するときに依存性注入を使用します。私が作成したクラスは次のとおりです。

public class MustBeValidWarehouse : ValidationAttribute 
{ 
    public override bool IsValid(object value) 
    { 
    if (value is string) 
    { 
     string warehouse = value.ToString(); 
     NinjectDependencyResolver depres = new NinjectDependencyResolver(); 
     Type inventServiceType = typeof(IInventService); 
     IInventService inventserv = depres.GetService(inventServiceType) as IInventService; 
     return (inventserv.GetWarehouses().Where(m => m.WarehouseId == warehouse).Count() != 0); 

    } 
    else 
    { 
     return false; 
    } 
    } 
} 


public class NinjectDependencyResolver : IDependencyResolver 
{ 
    private IKernel kernel; 
    public NinjectDependencyResolver() 
    { 
     kernel = new StandardKernel(); 
     AddBindings(); 
    } 

    public object GetService(Type serviceType) 
    { 
     return kernel.TryGet(serviceType); 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     return kernel.GetAll(serviceType); 
    } 

    private void AddBindings() 
    { 
     kernel.Bind<IInventService>().To<InventService>(); 
    } 
} 

依存性注入は正しく動作しますが、テストは容易ではありません。ユニットテストでは、模擬IInventServiceをクラスに挿入する方法はありません。通常これを解決するには、クラスコンストラクタにIInventServiceパラメータを渡して、単体テストでモックオブジェクトを渡すことができます。しかし、このクラスのコンストラクタにIInventServiceクラスをパラメータとして渡すことはできないと思うので、クラスでこの属性を追加したときにそのパラメータを渡す必要があると考えています。

このコードをよりテスト可能にする方法はありますか?もしそうでなければ、これにアプローチするより良い方法がありますか?

答えて

9

ASP.NET MVCでDependencyResolverクラスを使用する必要があります。コンテナを正しく配線すると、DependencyResolver.Currentはコンテナを使用して依存関係を解決します。

あなたはこのような DepedencyResolver.Currentためにモックを提供することができ、あなたのクラスのテストで
public class MustBeValidWarehouse : ValidationAttribute 
{ 
    public override bool IsValid(object value) 
    { 
     if (value is string) 
     { 
      string warehouse = value.ToString(); 
      IInventService inventserv = DependencyResolver.Current.GetService<IInventService>(); 
      return (inventserv.GetWarehouses().Where(m => m.WarehouseId == warehouse).Count() != 0); 
     } 
     return false; 
    } 
} 

DependencyResolver.SetResolver(resolverMock); 
+0

は素晴らしい仕事、ありがとうございました。 –