如何编写接口的junit测试? [英] How to write junit tests for interfaces?
问题描述
为接口编写junit测试的最佳方法是什么,以便它们可以用于具体的实现类?
What is the best way to write junit tests for interfaces so they can be used for the concrete implementing classes?
例如。你有这个接口和实现类:
e.g. You have this interface and implementing classes:
public interface MyInterface {
/** Return the given value. */
public boolean myMethod(boolean retVal);
}
public class MyClass1 implements MyInterface {
public boolean myMethod(boolean retVal) {
return retVal;
}
}
public class MyClass2 implements MyInterface {
public boolean myMethod(boolean retVal) {
return retVal;
}
}
您如何针对界面编写测试,以便您可以在课堂上使用吗?
How would you write a test against the interface so you can use it for the class?
可能性1:
public abstract class MyInterfaceTest {
public abstract MyInterface createInstance();
@Test
public final void testMyMethod_True() {
MyInterface instance = createInstance();
assertTrue(instance.myMethod(true));
}
@Test
public final void testMyMethod_False() {
MyInterface instance = createInstance();
assertFalse(instance.myMethod(false));
}
}
public class MyClass1Test extends MyInterfaceTest {
public MyInterface createInstance() {
return new MyClass1();
}
}
public class MyClass2Test extends MyInterfaceTest {
public MyInterface createInstance() {
return new MyClass2();
}
}
Pro:
- 只需要实施一种方法
Con:
- 所有测试中被测试类的依赖关系和模拟对象必须相同
可能性2:
public abstract class MyInterfaceTest
public void testMyMethod_True(MyInterface instance) {
assertTrue(instance.myMethod(true));
}
public void testMyMethod_False(MyInterface instance) {
assertFalse(instance.myMethod(false));
}
}
public class MyClass1Test extends MyInterfaceTest {
@Test
public void testMyMethod_True() {
MyClass1 instance = new MyClass1();
super.testMyMethod_True(instance);
}
@Test
public void testMyMethod_False() {
MyClass1 instance = new MyClass1();
super.testMyMethod_False(instance);
}
}
public class MyClass2Test extends MyInterfaceTest {
@Test
public void testMyMethod_True() {
MyClass1 instance = new MyClass2();
super.testMyMethod_True(instance);
}
@Test
public void testMyMethod_False() {
MyClass1 instance = new MyClass2();
super.testMyMethod_False(instance);
}
}
Pro:
- 每个测试的细粒度,包括依赖项和模拟对象
Con:
- 每个实施测试类都需要编写额外的测试方法
您更喜欢哪种可能性或者您使用其他什么方式?
Which possibility would you prefer or what other way do you use?
推荐答案
与投票得多的答案相反@dlev给出的,有时候写一个像你建议的测试非常有用/需要。通过其接口表示的类的公共API是最重要的测试。话虽如此,我不会使用你提到的方法,而是参数化测试,参数是要测试的实现:
Contrary to the much-voted-up answer that @dlev gave, it can sometimes be very useful/needful to write a test like you're suggesting. The public API of a class, as expressed through its interface, is the most important thing to test. That being said, I would use neither of the approaches you mentioned, but a Parameterized test instead, where the parameters are the implementations to be tested:
@RunWith(Parameterized.class)
public class InterfaceTesting {
public MyInterface myInterface;
public InterfaceTesting(MyInterface myInterface) {
this.myInterface = myInterface;
}
@Test
public final void testMyMethod_True() {
assertTrue(myInterface.myMethod(true));
}
@Test
public final void testMyMethod_False() {
assertFalse(myInterface.myMethod(false));
}
@Parameterized.Parameters
public static Collection<Object[]> instancesToTest() {
return Arrays.asList(
new Object[]{new MyClass1()},
new Object[]{new MyClass2()}
);
}
}
这篇关于如何编写接口的junit测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!