Java 测试实现相同接口的类的最佳方法
例如,我有几个类实现了Java 测试实现相同接口的类的最佳方法,java,junit,junit4,Java,Junit,Junit4,例如,我有几个类实现了List接口。如何测试它们——它们是否正确地实现了方法 现在我只看到一种方法: public class MyListImplementationsTest { private Collection<List<Integer>> listImplementations; @BeforeClass public static void setUp() throws Exception { listImpleme
List
接口。如何测试它们——它们是否正确地实现了方法
现在我只看到一种方法:
public class MyListImplementationsTest {
private Collection<List<Integer>> listImplementations;
@BeforeClass
public static void setUp() throws Exception {
listImplementations = Arrays.asList(
new QuickList<Integer>(), new EfficientMemoryList<Integer>()
);
}
@Test
public void testIsEmptyAfterCreationEmptyList() {
// Use forEachList(handler) in order to not iterate
// the lists manually every time.
// May be there is no need to do so,
// because using <<for (item : items)>> instead of
// iterating using index prevents from OutOfBounds errors
forEachList(new OnEachListHandler<Integer>() {
@Override
public void onEach(List<Integer> list) {
assertTrue(list.isEmpty());
}
});
}
private <T> void forEachList(OnEachListHandler<T> handler) {
for (List<T> each : listImplementations) {
handler.onEach(each);
}
}
private static interface OnEachListHandler<T> {
void onEach(List<T> each);
}
}
公共类MyListImplementsTest{
私有收集列表实现;
@课前
public static void setUp()引发异常{
listImplementations=Arrays.asList(
新建QuickList(),新建EfficientMemoryList()
);
}
@试验
CreationEmptyList()之后的公共无效证明{
//使用forEachList(处理程序)以避免迭代
//每次都手动创建列表。
//可能没有必要这样做,
//因为使用而不是
//使用索引进行迭代可防止边界外错误
forEachList(新的OnEachListHandler(){
@凌驾
公共无效onEach(列表){
assertTrue(list.isEmpty());
}
});
}
私有void forEachList(OnEachListHandler){
对于(列出每个:列表实现){
handler.onEach(每个);
}
}
私有静态接口OnEachListHandler{
void onEach(每个列表);
}
}
但在我看来,在每次测试中迭代列表是很复杂的
在
JUnit4
中是否有更优雅的方法来测试实现相同接口的类?您可以创建一个基本测试,它可以测试任何类型的List
以及一个创建这样一个列表的抽象方法
然后根据列表类型实现一个测试,该测试扩展了基本测试。JUnit将从基类以及您在扩展中定义的任何类运行测试用例
abstract class AbstractListTest<T> {
protected abstract List<T> createList();
@Test
public void testIsEmpty() {
List<T> list = createList();
assertTrue(list.isEmpty());
}
...more tests...
}
class QuickListTest extends AbstractListTest<QuickList> {
protected QuickList createList() {
return new QuickList();
}
}
抽象类AbstractListTest{
受保护的抽象列表createList();
@试验
公开无效证明(){
List=createList();
assertTrue(list.isEmpty());
}
…更多测试。。。
}
类QuickListTest扩展了AbstractListTest{
受保护的QuickList createList(){
返回新的快速列表();
}
}
JUnit不会运行抽象基类,但会看到继承的测试并运行所有测试。您还可以将新测试添加到QuickListTest
或重写基类中的测试
基本上,JUnit将使用该类,从整个继承树中查找所有公共的代码>代码>测试> /代码>方法。
< P>我将考虑将不同列表实现的测试分解到它们各自的测试用例中,使它们独立地通过或失败。p> 以您的.isEmpty()
为例,如果快速列表.isEmpty()
和效率记忆列表.isEmpty()
有不同的实现,即空的概念有不同的含义,那么独立测试它们是有意义的。当前,如果1个列表实现失败,则您的testIsEmptyAfterCreationEmptyList
将失败,但其他列表都已通过
否则,如果<代码> iSuthType()/<代码>和<代码>高效内存> .ISUNTY()/代码>共享相同的实现,那么您可以考虑将实现移动到公共基类,并为该基类编写测试。
仅仅因为类共享相同的接口,并不意味着它们的测试需要集中和耦合。分别为每个实现创建一个测试:QuickListTest
和EfficientMemoryListTest
QuickListTest.java
但是JUnit
如果基类是抽象的,那么如何从基类运行测试呢。JUnit将在超类上运行实现的方法。
public class QuickListTest extends ListBase {
@Test
public void shouldBeEmpty() throws Exception {
assertThatIsEmpty(new QuickList<Integer>());
}
}
public abstract class ListBase {
protected void assertThatIsEmpty(QuickList<Integer> actual) {
assertThat(actual).isEmpty();
}
}