依存性注入パターンに従ってコードを記述し、IoCフレームワークを使用する主な理由は、テスト可能なコードを取得することです。ただし、テストコードでIoCコンテナを使用すると、逆の結果になります。あなたの質問から私はあなたがすでにこれを体験しているのを見ることができます。
これは、依存関係注入(DI)パターンの代わりにサービス・ロケーター(SL)パターンを使用する場合に特に問題となります。 SLパターンでは、クラスはIoCコンテナ(またはそのようなコンテナの抽象化)を、必要な依存性をクラスに提供する代わりに(コンストラクタインジェクションを使用して)直接呼び出します。クラスはコンテナを直接呼び出しているため、テスト環境でもそのコンテナを設定する必要があります。テストフレームワークはあなたのテストを並行して実行するかもしれないので、テスト環境や偽のオブジェクトはしばしば非常に複雑になります。なぜなら、テストベースごとに偽の動作に影響を与えたいからです。 MSTestはこれを行います)。
あなたのアプリケーションコードにDIパターンを使用する必要があります。テストでは、あなたはあなたのテストでたとえば、HomeController
クラスのテストをICustomerService
クラスに依存する場合は、通常、テストクラスのHomeController
の作成を集中化するCreateController()
またはCreateValidController
ファクトリメソッドを使用する必要があります。このようなファクトリメソッドでは、クラスを手作業で以下のようにして注入します:
private static HomeController CreateController(
InMemoryDataMapper mapper)
{
var uowFactory = new FakeNorthwindUnitOfWorkFactory()
{
UnitOfWork = new NorthwindUnitOfWork(mapper);
};
return new HomeController(new FakeCustomerService(uowFactory));
}
HomeController
の依存関係の仕組みについては、そのようなファクトリメソッドはもちろんどのように見えますか(意図はありません)。
簡単に言えば、アプリケーションコードで実行したいのと同じ方法で、テストコードに依存性注入を行わないでください。テストフレームワークではこれを実行することが非常に難しいだけでなく、テスト環境用にIoCフレームワークを構成する必要があります。その場合は、失敗する可能性があります。残念ながら、私は経験から話します。
私はSLパターンを使用していません。幸いなことにコンストラクタインジェクションだけです。私は同じ懸念を抱いていて、MSBuildがデフォルトでは並行してテストを実行しないのを見ているので、並列テストに関する正確な質問をしていると思いますが、おそらく間違っています。 – Jeff
私はすべてのテストコードで依存関係の認識と有効期間の設定を複製する必要がありますか?言い換えれば、コンテナ内にシングルトンであるコンポーネントがあるとし、テストに必要な5つの一時コンポーネントのコンストラクタに注入する必要があるとします。シングルトンのインスタンスを手動でインスタンス化し、シングルトンとして保持して、手動でインスタンス化する各依存コンポーネントに注入することを知っているテストのセットアップを行う必要がありますか?コンポーネントがシングルトンにならない場合はどうなりますか?私はこのために私のテストセットアップコードをすべて書き直さなければならないのですか? – Jeff
インスタンスコンストラクタに注入するコンポーネントやサービスの可用性をテストするのはどうですか?インスタンシエーションを手動で行う場合は、この重要な機能をテストすることができません。状態を維持することは、通常、プログラミングのより繊細な部分の1つであり、コンポーネントの可用性をテストしていない場合は、状態管理の有効性を完全にテストすることができません。プログラミングにおける私の最も強い信念の1つはDRYです。具体的には、「2つの場所で状態を維持しないでください! – Jeff