ヌニットを使用したMEFとユニットテスト
-
27-09-2019 - |
質問
数週間前、私はMEF(ComponentModel)の時流に飛びつき、現在、多くのプラグインと共有ライブラリにそれを使用しています。全体として、私の側の頻繁な間違いは別として、それは素晴らしいことであり、その結果、デバッグセッションがイライラすることになります。
とにかく、私のアプリは素晴らしく実行されていますが、MEF関連のコードの変更により、自動化されたビルドが失敗しました。私のユニットテストのほとんどは、私がテストしていたモジュールがMEFがロードする必要がある他のモジュールに依存していたために失敗していました。 MEFをバイパスし、それらのオブジェクトを直接インスタンス化することにより、これらの状況を回避しました。
言い換えれば、MEFを介して私は
[Import]
public ICandyInterface ci { get; set; }
と
[Export(typeof(ICandyInterface))]
public class MyCandy : ICandyInterface
{
[ImportingConstructor]
public MyCandy( [Import("name_param")] string name) {}
...
}
しかし、私のユニットテストでは、私はただ使用します
CandyInterface MyCandy = new CandyInterface( "Godiva");
さらに、CandyInterfaceにはデータベースへの接続が必要です。これは、ユニットテストフォルダーにテストデータベースを追加するだけで進んでおり、すべてのテストにそれを使用しています。
さて、この状況に関する私の質問は次のとおりです。
- これは物事をするのに悪い方法ですか?
- セットアップ]で部品を作成することをお勧めしますか
- 私はまだユニットテストでモックを使用する方法を学んでいません - これは、基礎となるデータベース接続(どういうわけか)をmockしてダミーデータを返すだけで、実際にはデータベースを必要としない場合の良い例ですか?
- 以前にこのようなことに遭遇した場合、あなたの経験とあなたの問題を解決する方法を提供できますか? (または、これはコミュニティウィキに入るべきですか?)
解決
あなたは正しい軌道に乗っているように聞こえます。単位テストではテストする必要があります 単位, 、そしてそれはあなたがインスタンスを直接作成するときにあなたがすることです。あなたがmefにあなたのためにインスタンスを構成させた場合、彼らは 統合テスト. 。統合テストに何か問題があるわけではありませんが、各ユニットを単独でテストするため、単体テストはより保守可能になる傾向があります。
ユニットテストでインスタンスを配線するためにコンテナは必要ありません.
私は通常、セットアップで備品を作成することをお勧めします。 一般的なフィクスチャ アンチパターン。
依存関係を置き換えることがベストプラクティスです ダブルスをテストします. 。ダイナミックモックは、これを行うためのより多才な方法の1つなので、間違いなく学ぶべきことです。
他のヒント
ドキュメントを手動で作成することは、MEF組成コンテナを使用して輸入を満たすよりもはるかに優れていることに同意しますが、「セットアップの組成備品が一般的なフィクスチャーアンチパターンにつながる」というメモに関して、それは常にそうではないことを言及したいと思います。
静的コンテナを使用して、CompositionInitializer.Satisfyimportsを介して輸入を満たす場合、CompositionInitializer.Initializeとして、一般的なフィクスチャーアンチパターンに直面する必要があります。ただし、いつでもCompositionContainerを作成し、カタログを追加し、コンテナ自体にSatisyimportonceを呼び出すことができます。その場合、すべてのテストで新しいCompositionContainerを使用して、共有/一般的なフィクスチャーアンチパターンに直面することで逃げることができます
MEFでユニットテストを行う方法(ヌニットではなく、まったく同じ動作)を行う方法についてブログを書きました。トリックは、mockexportproviderを使用することであり、すべてのテストが継承するテストベースを作成しました。
これは、統合と単体テストに役立つ私の主な自動車機能です。
protected void AutoWire(MockExportProvider mocksProvider, params Assembly[] assemblies){
CompositionContainer container = null;
var assCatalogs = new List<AssemblyCatalog>();
foreach(var a in assemblies)
{
assCatalogs.Add(new AssemblyCatalog(a));
}
if (mocksProvider != null)
{
var providers = new List<ExportProvider>();
providers.Add(mocksProvider); //need to use the mocks provider before the assembly ones
foreach (var ac in assCatalogs)
{
var assemblyProvider = new CatalogExportProvider(ac);
providers.Add(assemblyProvider);
}
container = new CompositionContainer(providers.ToArray());
foreach (var p in providers) //must set the source provider for CatalogExportProvider back to the container (kinda stupid but apparently no way around this)
{
if (p is CatalogExportProvider)
{
((CatalogExportProvider)p).SourceProvider = container;
}
}
}
else
{
container = new CompositionContainer(new AggregateCatalog(assCatalogs));
}
container.ComposeParts(this);
}
私の投稿の詳細: https://yoavniran.wordpress.com/2012/10/18/unit-testing-wcf-and-mef/