junit5 入门系列教程-13-junit5 测试接口及默认方法
目录
- 目录
- 测试接口和默认方法
- 定义接口
- 测试案例
- 接口契约
- 接口定义
- 测试类
- 系列导航
测试接口和默认方法
JUnit Jupiter允许在接口默认方法上声明@Test、@RepeatedTest、@ParameterizedTest、@TestFactory、@TestTemplate、@BeforeEach和@AfterEach。
如果测试接口或测试类被@TestInstance(Lifecycle.PER_CLASS)注释,
则@BeforeAll和@AfterAll可以在测试接口中的静态方法上声明,也可以在接口默认方法上声明。
这里有一些例子。
定义接口
- TestLifecycleLogger.java
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.TestInstance;import java.util.logging.Logger;@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public interface TestLifecycleLogger {static final Logger LOG = Logger.getLogger(TestLifecycleLogger.class.getName());@BeforeAlldefault void beforeAllTests() {LOG.info("Before all tests");}@AfterAlldefault void afterAllTests() {LOG.info("After all tests");}@BeforeEachdefault void beforeEachTest(TestInfo testInfo) {LOG.info(() -> String.format("About to execute [%s]",testInfo.getDisplayName()));}@AfterEachdefault void afterEachTest(TestInfo testInfo) {LOG.info(() -> String.format("Finished executing [%s]",testInfo.getDisplayName()));}
}
- TestInterfaceDynamicTestsDemo.java
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;import java.util.Arrays;
import java.util.Collection;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;public interface TestInterfaceDynamicTestsDemo {@TestFactorydefault Collection<DynamicTest> dynamicTestsFromCollection() {return Arrays.asList(dynamicTest("1st dynamic test in test interface", () -> assertTrue(true)),dynamicTest("2nd dynamic test in test interface", () -> assertEquals(4, 2 * 2)));}
}
可以在测试接口上声明 @ExtendWith
和 @Tag
,以便实现该接口的类自动继承其标记和扩展。
查看测试执行前后对 TimingExtension 源代码的回调。
- TimeExecutionLogger.java
@Tag("timed")
@ExtendWith(TimingExtension.class)
interface TimeExecutionLogger {
}
- TimingExtension.java
import java.lang.reflect.Method;
import java.util.logging.Logger;import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;public class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {private static final Logger logger = Logger.getLogger(TimingExtension.class.getName());private static final String START_TIME = "start time";@Overridepublic void beforeTestExecution(ExtensionContext context) throws Exception {getStore(context).put(START_TIME, System.currentTimeMillis());}@Overridepublic void afterTestExecution(ExtensionContext context) throws Exception {Method testMethod = context.getRequiredTestMethod();long startTime = getStore(context).remove(START_TIME, long.class);long duration = System.currentTimeMillis() - startTime;logger.info(() -> String.format("Method [%s] took %s ms.", testMethod.getName(), duration));}private Store getStore(ExtensionContext context) {return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));}
}
测试案例
- TestInterfaceDemo.java
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertEquals;class TestInterfaceDemo implements TestLifecycleLogger,TimeExecutionLogger, TestInterfaceDynamicTestsDemo {@Testvoid 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
接口契约
这个特性的另一个可能的应用是为接口契约编写测试。
例如,您可以为对象的实现方式编写测试。Object.equals
的或 Comparable.compareTo
的。
接口定义
- Testable.java
public interface Testable<T> {T createValue();}
- EqualsContract.java
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;public interface EqualsContract<T> extends Testable<T> {T createNotEqualValue();@Testdefault void valueEqualsItself() {T value = createValue();assertEquals(value, value);}@Testdefault void valueDoesNotEqualNull() {T value = createValue();assertFalse(value.equals(null));}@Testdefault void valueDoesNotEqualDifferentValue() {T value = createValue();T differentValue = createNotEqualValue();assertNotEquals(value, differentValue);assertNotEquals(differentValue, value);}
}
- ComparableContract.java
import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;public interface ComparableContract<T extends Comparable<T>> extends Testable<T> {T createSmallerValue();@Testdefault void returnsZeroWhenComparedToItself() {T value = createValue();assertEquals(0, value.compareTo(value));}@Testdefault void returnsPositiveNumberComparedToSmallerValue() {T value = createValue();T smallerValue = createSmallerValue();assertTrue(value.compareTo(smallerValue) > 0);}@Testdefault void returnsNegativeNumberComparedToSmallerValue() {T value = createValue();T smallerValue = createSmallerValue();assertTrue(smallerValue.compareTo(value) < 0);}
}
测试类
在您的测试类中,您可以实现这两个契约接口,从而继承相应的测试。当然,您必须实现抽象方法。
- StringTest.java
public class StringTestimplements ComparableContract<String>, EqualsContract<String>{@Overridepublic String createValue() {return "foo";}@Overridepublic String createSmallerValue() {return "bar"; // 'b' < 'f' in "foo"}@Overridepublic String createNotEqualValue() {return "baz";}
}
系列导航
系列导航
junit5 入门系列教程-13-junit5 测试接口及默认方法相关推荐
- junit5 入门系列教程-02-junit5 注解详解
目录 目录 Junit5 注解 @Test @ParameterizedTest @RepeatedTest @TestFactory @TestInstance @TestTemplate @Dis ...
- junit5 入门系列教程-17-junit5 动态测试(DynamicTest)
目录 目录 动态测试 生命周期 测试案例 系列导航 动态测试 在标注中描述的JUnit Jupiter中的标准@Test注释与JUnit 4中的@Test注释非常相似.两者都描述了实现测试用例的方法. ...
- Provisioning Services 7.8 入门系列教程之十三 使用 Boot Device Management(BDM)
续Provisioning Services 7.8 入门系列教程之十二 实现高可用性 可以使用 Boot Device Management 实用程序将 IP 和引导信息(引导设备)交付给目标设备, ...
- Provisioning Services 7.8 入门系列教程之十四 UEFI支持和BOOTPTAB 编辑器
续Provisioning Services 7.8 入门系列教程之十三 使用 Boot Device Management(BDM) UEFI,全称Unified Extensible Firmw ...
- graphviz 画决策树_数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris
数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris 加载数据集 数据特征 训练 随机森林 调参工程师 结尾 数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iri ...
- Provisioning Services 7.8 入门系列教程之十一 通过版本控制自动更新虚拟磁盘
续Provisioning Services 7.8 入门系列教程之十 通过类自动更新虚拟磁盘 从前两的两种更新方式可以看出,它们有一个共同的特点,即需要产生(复制)完成的虚拟磁盘副本,然后进行相关的 ...
- html5游戏制作入门系列教程(八)
今天,我已经准备了一个新的游戏 – SkyWalker.基本上 – 这是用飞飞行模拟射击类游戏.我们的目标到达终点线.这个游戏还有其它一些特点,例如使用飞机运动动画和爆炸动画,多按键处理(例如同时移动 ...
- Provisioning Services 7.8 入门系列教程之五 使用Provisioning Services控制台
续Provisioning Services 7.8 入门系列教程之四 目标设备安装 使用 Provisioning Services 控制台可管理 Provisioning Services 场中的 ...
- STM32 基础系列教程 13 – ADC DMA
前言 学习stm32 adc模数转换接口使用,学会用STM32对模拟信号时行采样,通过DMA方式得到ADC结果. 示例详解 基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 ST ...
- html5游戏制作入门系列教程(七)
我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发.我们将要更新完善我们的第4课html5游戏制作入门系列教程(四)的游戏实例,并增加了火球,敌人和碰撞检测等功能模块.所以,现在我们的 ...
最新文章
- 水晶报表Crystal 语法 实用字段编辑
- 零基础自学python看什么书-零基础Python入门看哪本书好?这里有答案
- 蓝桥杯2015初赛-三羊献瑞-枚举
- 【Fudan DISC】一种无监督下利用多模态文档结构信息帮助图片-句子匹配的采样方法...
- 股票成本价买入价计算器 V1.3
- cef调用本地html,在CefSharp中使用本地构建的网页(Working with locally built web page in CefSharp)...
- cad2018安装教程_安装CAD后,我首先干了这些事!
- var that =this的用法详解
- 眼见不一定为实,电阻、电容和电感的实际等效模型
- 投稿时文章脚注数字如何去掉
- 标准盒子模型和IE盒子模型
- PV,UV,VV,IP
- CSS 成长之路(六)顶线、中线、基线、底线与行距
- u2020 华为_顶级锐龙标压U加持!华为MateBook 13 2020锐龙版评测:轻薄本稳压40W
- Android4.4 状态栏WiFi图标显示流程
- JavaScript Errors 指南
- 如何分析PARSEC源码
- 13:js逆向-登录加密(aes加密)
- 表白代码c语言,C语言告白代码,一闪一闪亮晶晶~
- CRC常用参数模型及C#代码实现
热门文章
- oppoR9s计算机使用方法,oppor9s怎么进入Recovery模式
- 翻遍知乎1000多个高赞回答,我找到了这7本计算机圣经
- 打印2018年的日历
- java 中怎么打印一个日历_日历打印用java实现
- 微信小程序语音播放功能的实现
- U1C3 介绍SketchEngine和Web语料库研究
- 【正点原子Linux连载】第六十五章 Linux 音频驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
- MQ消息队列的12点核心原理总结
- java计算机毕业设计家庭安防系统MyBatis+系统+LW文档+源码+调试部署
- 【C++】快速幂与矩阵快速幂