我想定义一个抽象基类,它定义了我想在测试各种 API 时一遍又一遍地实现的通用可重用测试用例。这个想法是定义一次测试,然后我可以从通用测试继承以获得测试定义,而我的测试代码所要做的就是实现如何执行测试的细节。这样我就不会错过好的测试用例,当我想出另一个好的测试用例来测试时,我不必重新发明轮子,也不必在几十个地方进行更改。
本质上,我正在做参数化测试,其中参数是在基类中定义的。预期结果也在基类中定义。但是,有时需要覆盖预期结果。例如,一个普通的字符串字段可能允许任何字符,而一个对象名称字段可能(或在我的情况下)限制哪些字符是合法的。例如,字符串字段允许“?” 在值中,名称字段没有。
我试图找出一种在基类中定义参数 ONCE 的干净方法,并且只定义一次预期结果,但可以选择在上下文需要的实现类中覆盖它。
我遇到的问题是,当您覆盖一个方法时,您必须替换它的实现。你不能只替换它的一部分。我想在不覆盖参数部分的情况下替换预期结果。我也不认为将每个测试分成两种方法是一种干净或理想的解决方案,一种提供参数,另一种定义预期行为。
我正在考虑的一种选择是使用注释来定义预期结果。然后我可以覆盖注解,然后将实现委托给基类实现。只要基类使用注释来决定如何表现,它就应该起作用。
例如:(在伪代码中,不是真正的 Java)
abstract class foo {
@fubar(true)
void test1() { doSomething( param1 ) }
@fubar(true)
void test2() { doSomething( param2 ) }
@fubar(false)
void test3() { doSomething( param3 ) }
boolean isFubar( void ) { ... } // generic annotation grabber
void doSomething( p ) {
if ( isFubar() )
doThis( p )
else
doThat( p );
}
// abstract methods to be defined in the implementing class
void doThis( p );
void doThat( p );
}
class bar extends foo {
// change the expected result for test2 only
@fubar(false)
void test2() { super.test2(); }
// define how to execute the tests
void doThis(p) { ... }
void doThat(p) { ... }
}
class baz extends bar {
// only changes the semantics of test3, nothing else
@fubar(true)
void test3() { super.test3() }
}
鉴于这种层次结构,foo.test1()
、bar.test1()
和baz.test1()
都做完全相同的事情。而foo.test2()
做一件事,又做另一bar.test2()
件事baz.test2()
。同样,foo.test3()
做bar.test3()
一件事,却baz.test3()
会有所不同。
我可以使用注释来完成此行为吗?如果是这样,isFubar
会是什么样子?我还没有看到方法名称未知的这种反射的示例。
作为旁注,如果有一种更清洁的方法来完成预期的行为,我很乐意听到它是什么。