それを実装するインターフェースと実装クラスがあり、このための単体テストを作成したいとします。インターフェイスまたはImplをテストする必要がありますか?
次に例を示します。
public interface HelloInterface {
public void sayHello();
}
public class HelloInterfaceImpl implements HelloInterface {
private PrintStream target = System.out;
@Override
public void sayHello() {
target.print("Hello World");
}
public void setTarget(PrintStream target){
this.target = target;
}
}
だから、私はそれを実装するHelloInterfaceとHelloInterfaceImplを持っています。ユニットアンダーテストインターフェイスまたはImplとは何ですか?
HelloInterfaceである必要があると思います。次のJUnitテストのスケッチを検討してください。
public class HelloInterfaceTest {
private HelloInterface hi;
@Before
public void setUp() {
hi = new HelloInterfaceImpl();
}
@Test
public void testDefaultBehaviourEndsNormally() {
hi.sayHello();
// no NullPointerException here
}
@Test
public void testCheckHelloWorld() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream target = new PrintStream(out);
PrivilegedAccessor.setValue(hi, "target", target);
//You can use ReflectionTestUtils in place of PrivilegedAccessor
//really it is DI
//((HelloInterfaceImpl)hi).setTarget(target);
hi.sayHello();
String result = out.toString();
assertEquals("Hello World", result);
}
}
メインラインは実際に私がコメントしたものです。
((HelloInterfaceImpl)hi).setTarget(target);
メソッドは私のパブリックインターフェイスの一部ではないので、誤って呼び出しsetTarget()
たくありません。本当に呼びたいのなら、少し時間を取って考えてみてください。たとえば、私が本当にやろうとしているのは依存性注入であることを発見するのに役立ちます。それは私に新しい機会の全世界を開きます。既存の依存性注入メカニズム(たとえば、Springのメカニズム)を使用できます。実際にコードで行ったように自分でシミュレートしたり、まったく異なるアプローチをとったりすることができます。よく見てください。PrintSreamの準備はそれほど簡単ではありませんでした。代わりにモックオブジェクトを使用する必要がありますか?
編集:私は常にインターフェースに焦点を当てるべきだと思います。私の観点からsetTarget()
は、implクラスの「コントラクト」の一部でもありません。依存性注入のサリーとして機能します。Implクラスのパブリックメソッドは、テストの観点からプライベートと見なす必要があると思います。ただし、実装の詳細を無視するという意味ではありません。
プライベート/保護されたメソッドを単体テストする必要がありますか?も参照してください。
EDIT-2複数の実装\複数のインターフェイスの場合、すべての実装をテストしますが、setUp()
メソッドで変数を宣言するときは、必ずインターフェイスを使用します。