我有很多简单的类实现一个简单的接口:
public interface MyInterface<T> {
public T value();
}
当然,我想为所有这些类创建单元测试。假设类MyClass implements MyInterface<String>
和以下示例:
public class MyClassTest {
@Test
public void valueTest() {
assertEquals(new MyClass(...).value(), ...);
}
@Test
public void performanceTest() {
assertTimeout(ofMillis(1), () -> new MyClass(...).value());
}
}
嗯,这种模式会重复很多次,所以应用模板可以帮助我简化工作。但是,我认为使用接口会更好,因为测试类实际上必须实现所有方法。
public interface MyInterfaceTestTemplate {
public void valueTest();
public void performanceTest();
}
在单元测试类中实现它:
public class MyClassTest implements MyInterfaceTestTemplate {
@Test
@Override
public void valueTest() {
assertEquals(new MyClass(...).value(), ...);
}
@Test
@Override
public void performanceTest() {
assertTimeout(ofMillis(1), () -> new MyClass(...).value());
}
}
我的问题是:
答案 0 :(得分:1)
通常建议不要继承单元测试,但我发现它完全没问题,只要你将基类的继承保持在一个级别和注释上就可以了。
这是我的意思的样本。这可能过于简化,但我只是在编写代码示例:
public class MyClass implements MyInterface<String>{
@Override
public String value() {
return "hi";
}
}
public abstract class AbstractTest<T> {
@Test
public void commonValueTest(){
assertEquals( createInstance().value(), getValueToCompare() );
}
@Test
public void commonPerformanceTest() {
assertTimeout( 1000, () -> createInstance().value() );
}
protected void assertTimeout(long mills, Runnable e){
/* add your imple */
}
protected abstract MyInterface<T> createInstance();
protected abstract T getValueToCompare();
}
public class MyClassTest extends AbstractTest<String>{
@Override
protected MyInterface<String> createInstance(){
return new MyClass();
}
@Override
protected String getValueToCompare(){
return "hi";
}
@Test
public void specificTest() {
/* your code */
}
}
答案 1 :(得分:1)
您可以使用Junt5的{em>参数化测试(https://blog.codefx.org/libraries/junit-5-parameterized-tests)代码:
@ParameterizedTest
@MethodSource(names = "createInterfaceImplAndCheckValue")
void testValue(MyInterface impl, Object value) {
assertEquals(impl.getValue(),value)
}
private static Stream<Arguments> createInterfaceImplAndCheckValue() {
return Stream.of(
ObjectArrayArguments.create(new MyInterfaceImpl1(), "hi"),
ObjectArrayArguments.create(new MyInterfaceImpl2(), 7));
}
@ParameterizedTest
@MethodSource(names = "createInterfaceImplAndTimeout")
void testPerformance(MyInterface impl, int timeout) {
assertTimeout(ofMillis(timeout), () -> impl.value());
}
private static Stream<Arguments> createInterfaceImplAndTimeout() {
return Stream.of(
ObjectArrayArguments.create(new MyInterfaceImpl1(), 1),
ObjectArrayArguments.create(new MyInterfaceImpl2(), 13));
}
原因你也可以将所有内容放在同一个“数据方法”中,只需忽略你不需要的参数:
@ParameterizedTest
@MethodSource(names = "createInterfaceImplAndCheckValue")
void testValue(MyInterface impl, Object value, int timeout) {
assertEquals(impl.getValue(),value)
}
@ParameterizedTest
@MethodSource(names = "createInterfaceImplAndCheckValue")
void testPerformance(MyInterface impl, Object value, int timeout) {
assertTimeout(ofMillis(timeout), () -> impl.value());
}
private static Stream<Arguments> createInterfaceImplAndCheckValue() {
return Stream.of(
ObjectArrayArguments.create(new MyInterfaceImpl1(), "hi", 1),
ObjectArrayArguments.create(new MyInterfaceImpl2(), 7, 12));
}