この質問は数日間私を悩ませてきました、そしてそれはいくつかの実践が互いに矛盾しているように感じます。
例
反復1
public class FooDao : IFooDao
{
private IFooConnection fooConnection;
private IBarConnection barConnection;
public FooDao(IFooConnection fooConnection, IBarConnection barConnection)
{
this.fooConnection = fooConnection;
this.barConnection = barConnection;
}
public Foo GetFoo(int id)
{
Foo foo = fooConection.get(id);
Bar bar = barConnection.get(foo);
foo.bar = bar;
return foo;
}
}
これをテストするとき、IFooConnectionとIBarConnectionを偽造し、FooDaoをインスタンス化するときに依存性注入(DI)を使用します。
機能を変更せずに実装を変更できます。
反復2
public class FooDao : IFooDao
{
private IFooBuilder fooBuilder;
public FooDao(IFooConnection fooConnection, IBarConnection barConnection)
{
this.fooBuilder = new FooBuilder(fooConnection, barConnection);
}
public Foo GetFoo(int id)
{
return fooBuilder.Build(id);
}
}
さて、このビルダーは書きませんが、FooDaoが以前に行ったのと同じことを想像してください。これは単なるリファクタリングであるため、機能が変更されることはありません。そのため、私のテストはまだ成功しています。
IFooBuilderは、ライブラリで機能するためだけに存在するため、内部です。つまり、APIの一部ではありません。
唯一の問題は、依存関係の逆転に準拠しなくなったことです。この問題を修正するためにこれを書き直した場合、次のようになります。
反復3
public class FooDao : IFooDao
{
private IFooBuilder fooBuilder;
public FooDao(IFooBuilder fooBuilder)
{
this.fooBuilder = fooBuilder;
}
public Foo GetFoo(int id)
{
return fooBuilder.Build(id);
}
}
これでうまくいくはずです。私はコンストラクタを変更したので、これをサポートするために(またはその逆に)テストを変更する必要がありますが、これは私の問題ではありません。
これをDIと連携させるには、FooBuilderとIFooBuilderをパブリックにする必要があります。これは、突然FooBuilderのライブラリのAPIの一部になったため、FooBuilderのテストを作成する必要があることを意味します。私の問題は、ライブラリのクライアントが、意図したAPI設計であるIFooDaoを介してのみ使用することであり、テストはクライアントとして機能します。依存関係の逆転に従わない場合、テストとAPIはよりクリーンになります。
言い換えれば、クライアントとして、またはテストとして私が気にしているのは、正しいFooを取得することであり、それを構築する方法ではありません。
ソリューション
私は単に気にしないでください、それはDIを喜ばせるためだけに公開されていますが、FooBuilderのテストを書いてください?-反復3をサポート
APIの拡張は依存関係の逆転の欠点であることを理解し、ここで準拠しないことを選択した理由を明確にする必要がありますか?-反復2をサポート
クリーンなAPIに重点を置いていますか?-反復3をサポート
編集:私は私の問題であることを、それを明確にしたいではない「?どのようにテストの内部に」ではなく、それはのようなもので、「私は内部のそれを維持し、まだDIPに準拠することができ、およびIばよいですか?」。
IFooBuilder
に公開する必要があるだけですか?FooBuilder
を返すためIFooBuilder
、内部にとどまることができる「デフォルトの実装を取得する」メソッドを介してDIシステムに公開する必要があるだけです。
public
ライブラリAPIとpublic
テストを区別したい」という異なる用語を使用して尋ねられています。または、「APIに表示されないようにメソッドをプライベートにしたいのですが、これらのプライベートメソッドをテストするにはどうすればよいですか?」その答えは、常に「より広範なパブリックAPIに対応する」、「パブリックAPIを介してテストに対応する」、または「メソッドinternal
を作成してテストコードに表示する」です。