如何为接口编写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();
}
}
专业:
- 只需要实现一种方法
缺点:
- 所有测试的被测类的依赖项和模拟对象必须相同
可能性 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);
}
}
专业:
- 每个测试的精细粒度,包括依赖项和模拟对象
缺点:
- 每个实现测试类都需要编写额外的测试方法
您更喜欢哪种可能性或您使用什么其他方式?
Which possibility would you prefer or what other way do you use?
推荐答案
与@dlev 给出的投票率高的答案相反,有时像您建议的那样编写测试非常有用/很有必要.类的公共 API,如通过其接口所表达的,是最重要的要测试的东西.话虽如此,我不会使用您提到的任何一种方法,而是使用 参数化 改为 test,其中参数是要测试的实现:
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屋!