2011-08-08 8 views
1

ASP.NET MVC 3アプリケーションのサービスレイヤーは、AutoMapperを使用してビューモデルをビジネスオブジェクトにマップします。私は型変換器を実装して、ポスト/取得リクエストで送信されたオブジェクトIDをビジネスオブジェクトに変換します。タイプコンバータはIDでデータベース内のエンティティをルックアップし、それらからビジネスを再構築します。たとえば:ユニットテストAutoMapperとタイプコンバータに依存するASP.NET MVCアプリケーションサービス

class UserViewModel { 
    // user fields 
    Guid? Manager; // this is an ID of another user in the system 
} 

サービスはAutoMapperを呼び出します:

var userModel = Mapper.Map<UserViewModel, UserModel>(viewModel); 

このクラスにマッピングするために:

class UserModel { 
    // other fields... 
    UserModel Manager; 
} 

データベースに別のユーザーを見上げ型コンバータの助けを借りてビューモデルからのマネージャGUIDによるタイプコンバータは、Ninjectを使用して依存関係を注入され、すべてがWebアプリケーションで正常に動作します。

私はタイプコンバータを備えたモックリポジトリを使用する単体テストを作成しようとしています。 AutoMapperは、ユーザ提供の関数を使用してサービスを構築するように構成することができます:Webアプリケーションカーネルで

Mapper.Initialize(cfg => 
{ 
    cfg.ConstructServicesUsing(type => Kernel.GetService(type)); 
}); 

はNinjectで、私は辞書から要求された型のインスタンスを返します。私自身の方法で提供することを決定したテストのために:

Dictionary<Type, object> typeDict = new Dictionary<Type, object>() 
{ 
    { typeof(IRepository), new MockRepository() } 
}; 

... 
Mapper.Initialize(cfg => 
{ 
    cfg.ConstructServicesUsing(type => { return typeDict[type]; }); 
}); 

アイデアはAutoMapperは、このようなオブジェクトにGUIDを変換するように構成されている場合ということであった:

Mapper.CreateMap<Guid?, TDropDown>() 
     .ConvertUsing<GuidToSelectListValueConverter<TDropDown>>(); 

と新しいインスタンス0を作成する必要がありますf GuidToSelectListValueConverterを開き、リポジトリを挿入して、ConstructServicesUsingで設定されたメソッドを使用してIRepositoryタイプを要求します。

代わりに、AutoMapperは実際にGuidToSelectListValueConverterタイプのインスタンスを取得しようとします。これは、型変換器の新しいインスタンスを作成し、それに依存関係を注入する責任を負うことを意味します。私typeDictではなく、次のようになります。

Dictionary<Type, object> typeDict = new Dictionary<Type, object>() 
{ 
    { typeof(GuidToSelectListValueConverter), new GuidToSelectListValueConverter(
       new MockRepository()) } 
}; 

を私は型コンバータの多くを持って、手動でそれらの実現可能思われないためにリゾルバ関数を記述します。それで、私は思考を得ました。単体テストでこれらの依存関係を解決するためにNinjectを単純に構成するのは間違っていますか?私はIRepositoryをMockRepositoryにバインドすることができ、サービスのインスタンスが必要なときには単にKernel.GetService(typeof(MyService))を呼び出し、NinjectにMockRepositoryを注入させるだけです。

// configure Ninject 
Kernel.Bind<IRepository>().To<MockRepository>(); 
// initialize AutoMapper 
Mapper.Initialize(cfg => 
{ 
    cfg.ConstructServicesUsing(t => Kernel.GetService(t)); 
}); 
// create an instance of service to test 
var service = Kernel.GetService(IMyService); 
// do work 
var result = service.DoWork(); 
// analyze result 

今DoWorkメソッドはMapper.Map形コンバータはNinjectを使用して作成され呼び出すとき:追加の利点は、AutoMapperも型コンバータと値リゾルバのインスタンスを取得するにはNinjectを使用することです。

アドバイス、アイデア、ベストプラクティスのアドバイスは大歓迎です。

ありがとうございました!

答えて

1

チェックアウトthis post on using IoC with AutoMapper

これは私のコントローラーでMapperの代わりにIMappingEngineを使用することによって正しい方向に進むのに役立ちました。

+0

ありがとうDave、私はIMappingEngineへの依存を追加し、テストでそれを嘲笑することが行く方法です。 – LeffeBrune

+0

驚いたことに、ビューモデルをサービス内のモデルにマップするほど愚かではない場合、驚くべきことに、全体の問題を回避することができました。 – LeffeBrune

関連する問題