各モジュールがサービスを注入/解決できるように、ブートストラップが各モジュールに DI コンテナーを渡す複数のモジュール (IModule) で構成される PRISM アプリケーションがあります。これは、各モジュールには、型が注入/解決される独自の「コンポジション ルート」があることを意味し、それらの単体テストについてベスト プラクティスが何を言っているのか疑問に思っていました。
たとえば、さまざまなデータ ソースからデータをフェッチするサービスの作成と登録を担当する Resources モジュールがあるとします。次のように IModule.Initialize メソッドを実装するとします。
void Initialize()
{
ISomeDataService someDataService = _container.Resolve<SomeDataService>();
someDataService.Connect();
_container.RegisterInstance<ISomeDataService>(someDataService);
}
Resources モジュールは SomeDataService のインスタンスを作成し、接続を開き、他のモジュールが使用できるように登録します。注 : これは実際に私が行っている方法ではありません。簡単な説明のためのものです。
単体テストの観点から、Initialize メソッドをテストするにはどうすればよいでしょうか。ここで 2 つのことをテストします。
ISomeDataService.Connect()
メソッドが呼び出されています。IUnityContainer.RegisterInstance
が呼び出され、正しいサービスが提供されます。
実際に具体的な型を作成してInitialize()
登録するのはISomeDataService
. 今では具象型を解決しようとしますSomeDataService
(これは基本的に を実行するのと同じことですnew SomeDataService()
)。そのため、具象型をモックして、SomeDataService
テストしたいメソッドをオーバーライドしようとすることができますが、具象型に副作用がある場合、これは問題になります。インスタンス化直後に有効な WCF バインディングを解決しようとし、失敗すると例外をスローする ChannelFactory などです。有効なバインディングを提供することでその失敗を回避できますが、単体テストはそのようなものに依存するべきではないと思います。
何かアドバイス?私が持っていた1つのアイデアは次のとおりです。
void Initialize()
{
if (_container.IsRegistered<ISomeDataService>())
{
someDataService = _container.Resolve<ISomeDataService>();
}
else
{
someDataService = _container.Resolve<SomeDataService>(); // or new SomeDataService()
}
_container.RegisterInstance<ISomeDataService>(someDataService);
someDataService.Connect();
}
このようにすると、具象型 SomeDataService の代わりに ISomeDataService をモックでき、すべて問題ありませんが、これが正しいアプローチであるかどうかはわかりません...これは間違っていると確信しており、他の方法があるはずです.