Каков наилучший способ написания тестов junit для интерфейсов, чтобы их можно было использовать для конкретных классов реализации?
например. У вас есть этот интерфейс и реализующие классы:
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;
}
}
Как вы могли бы написать тест против интерфейса, чтобы вы могли использовать его для класса?
Возможность 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:
- Каждому классу-тестированию требуется написать дополнительные методы тестирования
Какую возможность вы предпочитаете или какой другой способ используете?