我的项目里的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//TimeOutAssertions.assertThrows(); // JUnit5Assertions.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