目录
- 目录
-
测试接口和默认方法
- 定义接口
- 测试案例
-
接口契约
- 接口定义
- 测试类
- 系列导航
测试接口和默认方法
JUnit Jupiter允许在接口默认方法上声明@Test、@RepeatedTest、@ParameterizedTest、@TestFactory、@TestTemplate、@BeforeEach和@AfterEach。
如果测试接口或测试类被@TestInstance(Lifecycle.PER_CLASS)注释,
则@BeforeAll和@AfterAll可以在测试接口中的静态方法上声明,也可以在接口默认方法上声明。
这里有一些例子。
定义接口
import ;
import ;
import ;
import ;
import ;
import ;
import ;
@TestInstance(.PER_CLASS)
public interface TestLifecycleLogger {
static final Logger LOG = (());
@BeforeAll
default void beforeAllTests() {
("Before all tests");
}
@AfterAll
default void afterAllTests() {
("After all tests");
}
@BeforeEach
default void beforeEachTest(TestInfo testInfo) {
(() -> ("About to execute [%s]",
()));
}
@AfterEach
default void afterEachTest(TestInfo testInfo) {
(() -> ("Finished executing [%s]",
()));
}
}
import ;
import ;
import ;
import ;
import static ;
import static ;
import static ;
public interface TestInterfaceDynamicTestsDemo {
@TestFactory
default Collection<DynamicTest> dynamicTestsFromCollection() {
return (
dynamicTest("1st dynamic test in test interface", () -> assertTrue(true)),
dynamicTest("2nd dynamic test in test interface", () -> assertEquals(4, 2 * 2))
);
}
}
可以在测试接口上声明 @ExtendWith
和 @Tag
,以便实现该接口的类自动继承其标记和扩展。
查看测试执行前后对 TimingExtension 源代码的回调。
@Tag("timed")
@ExtendWith()
interface TimeExecutionLogger {
}
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
private static final Logger logger = (());
private static final String START_TIME = "start time";
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
getStore(context).put(START_TIME, ());
}
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
Method testMethod = ();
long startTime = getStore(context).remove(START_TIME, long.class);
long duration = () - startTime;
(() -> ("Method [%s] took %s ms.", (), duration));
}
private Store getStore(ExtensionContext context) {
return ((getClass(), ()));
}
}
测试案例
import ;
import static ;
class TestInterfaceDemo implements TestLifecycleLogger,
TimeExecutionLogger, TestInterfaceDynamicTestsDemo {
@Test
void isEqualValue() {
assertEquals(1, 1, "is always equal");
}
}
日志如下:
Jun 25, 2018 6:18:43 PM com.github.houbb.jdk.junit5.interfaces.TestLifecycleLogger beforeAllTests
信息: Before all tests
Jun 25, 2018 6:18:43 PM com.github.houbb.jdk.junit5.interfaces.TestLifecycleLogger beforeEachTest
信息: About to execute [isEqualValue()]
Jun 25, 2018 6:18:43 PM com.github.houbb.jdk.junit5.interfaces.TimingExtension afterTestExecution
信息: Method [isEqualValue] took 4 ms.
Jun 25, 2018 6:18:43 PM com.github.houbb.jdk.junit5.interfaces.TestLifecycleLogger afterEachTest
信息: Finished executing [isEqualValue()]
Jun 25, 2018 6:18:43 PM com.github.houbb.jdk.junit5.interfaces.TestLifecycleLogger afterAllTests
信息: After all tests
接口契约
这个特性的另一个可能的应用是为接口契约编写测试。
例如,您可以为对象的实现方式编写测试。 的或
的。
接口定义
public interface Testable<T> {
T createValue();
}
import ;
import static ;
import static ;
import static ;
public interface EqualsContract<T> extends Testable<T> {
T createNotEqualValue();
@Test
default void valueEqualsItself() {
T value = createValue();
assertEquals(value, value);
}
@Test
default void valueDoesNotEqualNull() {
T value = createValue();
assertFalse((null));
}
@Test
default void valueDoesNotEqualDifferentValue() {
T value = createValue();
T differentValue = createNotEqualValue();
assertNotEquals(value, differentValue);
assertNotEquals(differentValue, value);
}
}
import ;
import static ;
import static ;
public interface ComparableContract<T extends Comparable<T>> extends Testable<T> {
T createSmallerValue();
@Test
default void returnsZeroWhenComparedToItself() {
T value = createValue();
assertEquals(0, (value));
}
@Test
default void returnsPositiveNumberComparedToSmallerValue() {
T value = createValue();
T smallerValue = createSmallerValue();
assertTrue((smallerValue) > 0);
}
@Test
default void returnsNegativeNumberComparedToSmallerValue() {
T value = createValue();
T smallerValue = createSmallerValue();
assertTrue((value) < 0);
}
}
测试类
在您的测试类中,您可以实现这两个契约接口,从而继承相应的测试。当然,您必须实现抽象方法。
public class StringTest
implements ComparableContract<String>, EqualsContract<String>{
@Override
public String createValue() {
return "foo";
}
@Override
public String createSmallerValue() {
return "bar"; // 'b' < 'f' in "foo"
}
@Override
public String createNotEqualValue() {
return "baz";
}
}
系列导航
系列导航