共计 2634 个字符,预计需要花费 7 分钟才能阅读完成。
我的项目里的 UT 越来越慢,怎么办?
JUnit 是一个 Java 语言的单元测试框架。它由 Kent
Beck 和 Erich Gamma 建设,逐步成为源于 Kent Beck 的 sUnit 的 xUnit 家族中最为胜利的一个。
JUnit 有它本人的 JUnit 扩大生态圈。少数 Java 的开发环境都曾经集成了 JUnit 作为单元测试的工具。
它曾经倒退有 20 余年历史了
当初咱们的我的项目在 Jenkins 流水线上每次部署时,随着 code 越来越多,UnitTest 这部分 Stage 也每次都跑得最慢,怎么能够加快速度呢?
能够试着从 code 层面去尝试 refactor,比方将 Junit4 降级到更好效率更快的 Junit5
JUnit5
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JDK Version >= 8 (而 JUnit4 是要求 JDK Version >= 5)
JUnit 平台 | 它定义了 TestEngine 用于开发在平台上运行的新测试框架的 API |
---|---|
JUnit Jupiter | 它具备所有新的 junit 正文和 TestEngine 实现,以运行应用这些正文编写的测试 |
JUnit Vintage | 反对在 JUnit 5 平台上运行 JUnit 3 和 JUnit 4 编写的测试 |
JUnit5 的规范用法
-
集成 Spring(The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5 | Baeldung)
- 应用 JUnit5 的拓展模型个性,@ExtendWith(SpringExtension.class),能够应用 Spring 的上下文装载性能,而不必去应用重量级的 @SpringBootTest
-
集成 Mockito(Mockito and JUnit 5 – Using ExtendWith | Baeldung)
- 引入 JUnit5 和 Mockito 的 maven 依赖
- 配置 Surefire Plugin,使得测试代码都运行在新的 JUnit 平台上
- 有必要兼容 JUnit4 的测试代码的话,还需退出 JUnit5 vintage-engine 的 maven 依赖
- @ExtendWith(MockitoExtension.class), 集成 Mockito,能够应用 @Mock, @Spy, @InjectMocks 等注解,不便咱们写 UT
JUnit 4 VS JUnit 5
- 注解的区别
-
注解的应用区别
- 罕用的
//Exception @Test(expected = Exception.class) // JUnit4 @Test(timeout = 1) // JUnit4 //TimeOut Assertions.assertThrows(); // JUnit5 Assertions.assertTimeout(1); //JUnit5
-
@RunWith 和 @ExtendWith(最大个性差别)
@RunWith 用于将测试上下文与其余框架集成或更改 JUnit 4 中测试用例中整体执行流程
而在 JUnit 5 中,咱们当初能够应用 @ExtendWith 注解来提供相似的性能
@RunWith(SpringJUnit4ClassRunner.class) public class SpringExtensionTest {/* JUnit4 */} @ExtendWith(SpringExtension.class) public class SpringExtensionTest {/* JUnit5 */}
为什么要应用 JUnit5
-
粒度更细
JUnit 4 有一些显著的限度:整个框架蕴含在一个 jar 库中,即便只须要特定性能,也须要导入整个库
而在 JUnit 5 中,咱们取得了更多的粒度,并且能够只导入必要的内容 -
同时运行多个运行器
一个测试运行器一次只能在 JUnit 4 中执行测试(例 SpringJUnit4ClassRunner 或 Parameterized)
而在 JUnit 5 容许多个运行器同时工作 -
赶上 JDK8 的浪潮
这个大家写过 Java 的,懂得都懂
降级
-
将 @SpringBootTest 以及 @RunWith(SpringRunner.class 或者 SpringJUnit4ClassRunner)移除,换成 JUnit5 拓展新个性 @ExtendWith(SpringExtension.class)
Spring Boot 提供了
@SpringBootTest
注解,咱们能够应用它来创立一个应用程序上下文,其中蕴含所有上述测试类型所需的所有对象。然而请留神,适度应用@SpringBootTest
可能会导致 测试套件运行工夫过长SpringRunner 继承自 SpringJUnit4ClassRunner
-
将所有 org.junit.的 import,都换成 org.junit.jupiter.
(Migrating from JUnit 4 to JUnit 5 | Baeldung)
优化思路
- 多应用 Mockito 轻量级的工具 去写 UT
@ExtendWith(MockitoExtension.class)
须要用到 Spring Context,就可应用 @ExtendWith(SpringExtension.class) - 在代码层面能够将 @Autowired 换成,结构器注入,与 Spring 解耦合,不然写 UT 须要注入 Bean 的时候,就不得不应用 Spring 容器
- 少应用 @MockBean,@SpyBean 这些 Spring 提供的正文,尽管它能够帮咱们轻松应用 Mockito 的 Mock 性能。让 Spring Boot 性能很容易蕴含在咱们的测试中,但咱们应该意识到老本:每个测试都可能创立一个新的应用程序上下文,这可能会显着减少测试套件的运行工夫,而这恰好也就是你 UT 跑得慢的起因!
-
除了在写集成测试时用到 @SpringBootTest,其余均不必,不得已要应用的话,也尽可能尽着 少加载 Bean 的指标,去写 code,越少 bean 加载,速度就越快
- classes 指定须要 装载的 class
- webEnvironment 不应用时关掉(不过如同默认是关的)
- 降级 JUnit5
说在最初
UT 这种货色,当然是覆盖率和品质越高越好,但也取决于我的项目的赶工水平,又想 马儿跑,有不给马儿吃草,这种本就不事实
但作为开发人员,大家要对技术有肯定理解,不要老是 copy 前人代码的改改改,因为他人的不肯定是对的,也不肯定是最好的,只能阐明,它是稳固且不怎么出大问题的
最初 好文举荐:
- Mockito Tutorial | Baeldung
- Learn JUnit | Baeldung