我想为不同的接口实现运行相同的JUnit测试.我用@Parameter选项找到了一个很好的解决方案:
public class InterfaceTest{
MyInterface interface;
public InterfaceTest(MyInterface interface) {
this.interface = interface;
}
@Parameters
public static Collection<Object[]> getParameters()
{
return Arrays.asList(new Object[][] {
{ new GoodInterfaceImpl() },
{ new AnotherInterfaceImpl() }
});
}
}
Run Code Online (Sandbox Code Playgroud)
此测试将运行两次,首先使用GoodInterfaceImpl,然后使用AnotherInterfaceImpl类.但问题是我需要大多数测试用例是一个新对象.一个简化的例子:
@Test
public void isEmptyTest(){
assertTrue(interface.isEmpty());
}
@Test
public void insertTest(){
interface.insert(new Object());
assertFalse(interface.isEmpty());
}
Run Code Online (Sandbox Code Playgroud)
如果在insertTest之后运行isEmptyTest则失败.
是否有选项可以使用新的实现实例自动运行每个测试用例?
顺便说一句:为接口实现clear()或reset()方法实际上不是一个选项,因为我不需要它在生产代码中.
创建一个工厂接口和实现,如果您在生产中不需要这样的东西,可能只在您的测试层次结构中创建,并getParameters()返回一个工厂列表。
然后,您可以在带@Before注释的方法中调用工厂,以便为每个测试方法运行获取被测实际类的新实例。
小智 5
以下是使用模板方法模式的另一种方法:
面向接口的测试进入基类:
public abstract class MyInterfaceTest {
private MyInterface myInterface;
protected abstract MyInterface makeContractSubject();
@Before
public void setUp() {
myInterface = makeContractSubject();
}
@Test
public void isEmptyTest(){
assertTrue(myInterface.isEmpty());
}
@Test
public void insertTest(){
myInterface.insert(new Object());
assertFalse(myInterface.isEmpty());
}
}
Run Code Online (Sandbox Code Playgroud)
对于每个具体类,定义一个具体的测试类:
public class GoodInterfaceImplTest extends MyInterfaceTest {
@Override
protected MyInterface makeContractSubject() {
// initialize new GoodInterfaceImpl
// insert proper stubs
return ...;
}
@Test
public void additionalImplementationSpecificStuff() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
与@Parameter相比,稍微优点是您可以获得测试失败时报告的具体测试类的名称,因此您可以立即知道哪个实现失败.
顺便说一下,为了使这种方法完全起作用,必须以允许通过接口方法进行测试的方式设计接口.这意味着基于状态的测试 - 您无法验证基础测试类中的模拟.如果需要在特定于实现的测试中验证模拟,则这些测试必须进入具体的测试类.
| 归档时间: |
|
| 查看次数: |
2167 次 |
| 最近记录: |