Junit5使用示例

Junit5使用示例junit5 使用详解

一、创建单元测试service

二、示例代码

// 取dev环境配置文件 @ActiveProfiles("dev") // 指定启动类 @SpringBootTest(classes = ProjectApplication.class) // 如果想在测试中使用Spring测试框架功能(例如)@MockBean,则必须使用@ExtendWith(SpringExtension.class)。 // 它取代了不推荐使用的JUnit4@RunWith(SpringJUnit4ClassRunner.class) @ExtendWith(SpringExtension.class) public class AppApplicationManagerServiceTest { 
    // 需要加了@SpyBean或@MockBean注解才可以模板方法返回值 // @SpyBean注解如果没有模拟方法返回,会调用真实方法 @SpyBean private AppApplicationManagerService appApplicationManagerService; // @MockBean注解如果没有模拟方法返回,会返回null @MockBean private CommonService commonService; @BeforeEach // 每个测试方法之前都会执行一次 public void setUp() { 
    when(commonService.getOsreIdByCode(Mockito.anyString())).thenReturn(107); } // 最终结果显示名称 @DisplayName("根据租户编码+应用编码获取应用管理员列表") // 参数化测试,可以与@CsvSource、@EnumSource、@MethodSource等注解结合使用 @ParameterizedTest // 参数以逗号分隔,以此为例,会执行三次这个测试方法,参数分别对应 @CsvSource({ 
    "dev002, SP-CI, hrdashboard", "dev002, CDPLIFE, hrdashboard", "dev002, third, hrdashboard" }) public void testGetApplicationManager(String tenantCode, String appCode, String sysCode) { 
    // 如果调用了appRoleMapper.selectByExample(any())方法,参数为任意类型对象,会返回null // 与数据库相关操作或调用其他微服务操作可以使用这个方法模拟返回值 when(appRoleMapper.selectByExample(any())).thenReturn(null); // 执行测试方法 List<String> resList = appApplicationManagerService.getApplicationManager(tenantCode, appCode, sysCode); if ("SP-CI".equals(appCode)) { 
    boolean judge = DataUtils.isEmptyList(resList); // 断言,每个测试方法断言最好大于等于1 assertTrue(judge); } } } 

三、注解

1、@SpyBean、@MockBean、@Autowired

  • 如果不需要模拟方法返回值,可以使用@Autowired或@SpyBean
  • 如果既需要调用真实方法,也需要模拟方法返回值,只能使用@SpyBean
  • 如果只需要模拟方法返回值,可以使用@MockBean或@SpyBean

2、@ExtendWith(SpringExtension.class)

如果想在测试中使用Spring测试框架功能(例如)@MockBean,则必须使用@ExtendWith(SpringExtension.class)。它取代了不推荐使用的JUnit4@RunWith(SpringJUnit4ClassRunner.class)

3、@BeforeEach、@BeforeAll、@AfterAll、@AfterEach

  • @BeforeEach:每个测试方法执行之前都会执行
  • @AfterEach:每个测试方法执行结束都会执行
  • @BeforeAll:所有测试方法执行之前会执行
  • @AfterAll所有测试方法执行之后会执行

4、@DisplayName()

运行结果中该方法显示的名称

5、@ParameterizedTest、@RepeatedTest()

参数化测试,使用时需要替换掉@Test,同时需要最少增加一个源,该源将为每个调用提供参数,然后使用测试方法中的参数。如

@ParameterizedTest @CsvSource({ 
    "dev002, SP-CI, hrdashboard", "dev002, CDPLIFE, hrdashboard", "dev002, third, hrdashboard" }) 

这表示,添加了这两个注解的方法会执行三次,每次会传入三个参数

@RepeatedTest(n):重复性测试,即执行n次

6、@ValueSource、@EnumSource、@MethodSource、@CsvSource、@CsvFileSource、@ArgumentsSource

这些注解都是和@ParameterizedTest组合使用,用来指定参数源的。

// 执行三次方法,类型还支持float、String、long等类型 @ValueSource(ints = { 
    1, 2, 3 }) 
// @EnumSource提供了使用Enum常量的方便方法。该注释提供了一个可选的名称参数,允许您指定哪个常量应使用。如果省略,所有的常量将被使用,如下面的示例所示。 @EnumSource(TimeUnit.class) 
// @MethodSource 允许引用测试类或外部类的一个或多个方法。此类方法必须返回流、可迭代、迭代器或参数数组。此外,这种方法不能接受任何参数。测试类中的工厂方法必须是静态的,除非用@TestInstance(Lifecycle.PER_CLASS)注释测试类; @MethodSource("roleAndMenuParam") void testSavePlatformRoleAndAuthMenu(PlatformAdminAuthMenuForm platformAdminAuthMenuForm) { 
    } static List<PlatformAdminAuthMenuForm> roleAndMenuParam() { 
    } 
// 参数以逗号分隔,以此为例,会执行三次这个测试方法,传入三个参数 @CsvSource({ 
    "dev002, SP-CI, hrdashboard", "dev002, CDPLIFE, hrdashboard", "dev002, third, hrdashboard" }) 
// @CsvFileSource允许使用类路径中的CSV文件。CSV文件中的每一行都会调用一次参数化测试。 @CsvFileSource(resources = "/two-column.csv", numLinesToSkip = 1) 

@ArgumentsSource 可用于指定自定义的、可重用的ArgumentsProvider。

7、@Disabled

添加了该注解的方法运行的时候不会执行

四、断言

断言在每个测试方法建议最少有一个

Junit5的断言支持Lambda表达式

以下列举部分常见断言:

  • assertEquals:断言预期和实际是相等的
  • assertNotNull:结果不是null
  • assertThrows:校验异常,如果没有抛出异常或者抛出的异常与预期异常不一致,会断言失败
  • assertAll:分组断言,可以由多个断言组合而成,只要其中有一个不通过就不会继续执行

更多断言不一一列举

五、模拟方法返回值

在写单元测试的时候,有时会需要让方法返回自己想要的结果,这个时就需要使用mock来模拟方法的返回值

mockito实现模拟的原理是通过反射创建一个继承了原类的匿名子类,使用创建的子类代替原来的类执行,由于是继承,所以静态方法、final方法、私有方法无法通过子类进行重写

模拟返回值

// 原方法 appRoleMapper.selectByExample(AppRoleExample example); // 模拟返回值 when(appRoleMapper.selectByExample(any())).thenReturn(null); 

这个方法的作用是指在后面的代码中如果执行到appRoleMapper.selectByExample(AppRoleExample example)方法,参数为任意类型参数,都不会去调用数据库,会直接返回null

doNothing

有些方法没有返回值,如发送消息等方法,如果不需要调用这些方法,可以使用doNothing方法,这样遇到这个方法就不会去执行这个方法,示例如下:

// 原方法 commonService.verifyFieldRequired(Object obj, String jsonPaths){ 
   } // doNothing使用 Mockito.doNothing().when(commonService).verifyFieldRequired(Mockito.any(), Mockito.anyString()); 

Mockito参数

在模拟方法的时候,需要参数,可以指定any()或anyString()等来指定参数类型,any表示任意类型对象,anyString()表示任意String类型参数,其他类型:

any(Class type):可以传具体的类进来,如果any(AppRole.class)代表任意的角色对象

anyBoolean():任意boolean类型数据

anyListOf(Class clazz):代表某个类型的列表

anyObject():任意对象

更多方法不一一列举

创建模拟对象

测试数据有时候需要的比较多,一个一个创建比较繁琐,可以使用EasyRandom创建随机对象

EasyRandom easyRandom = new EasyRandom(); // 生成单个对象 AppMenu menu = easyRandom.nextObject(AppMenu.class); // 生成列表 List<AppMenu> menuList = easyRandom.objects(AppMenu.class, 10).collect(Collectors.toList()); // 生成其他类型数据 boolean boo = easyRandom.nextBoolean(); 

如果不设置参数,随机生成的数据比较乱,可以加一个配置,使得生成的数据更符合我们的要求,使用方法如下

EasyRandomParameters param = new EasyRandomParameters(); // 设置字符串长度范围 param.setStringLengthRange(new Range(5,10)); // 创建对象的时候将配置参数传入 EasyRandom easyRandom = new EasyRandom(param); for (int i = 0; i < 5; i++) { 
    String str = easyRandom.nextObject(String.class); System.out.println(str); } // 结果 tniOAot nzWvk QtWruzGVy IdgFUY NdkFYkk 

更多配置请查看官方文档:https://github.com/j-easy/easy-random/wiki/Randomization-parameters

模拟静态方法、私有方法返回值

前面有说到mockito是通过反射创建原类的子类来实现的模拟,这样的方法无法模拟静态方法、私有方法、final方法,此时可以使用JMockit来实现

JMockit中文网:http://jmockit.cn/index.htm

JMock使用方法一:

class LogTestServiceTest { 
    @Autowired private static LogTestService logTestService = new LogTestService(); @Test void testTest() throws Exception { 
    new Expectations(DataUtils.class, LogTestService.class) { 
    { 
    // mock静态方法 DataUtils.isEmptyList(Mockito.anyList()); result = false; // mock final方法 logTestService.finalTest(Mockito.anyString()); result = "mock final"; // 私有方法与native方法不可以通过这个方式mock } }; logTestService.test(); } } 

JMock使用方法二:

class LogTestServiceTest { 
    @Autowired private static LogTestService logTestService = new LogTestService(); // 写一个内部类,继承MockUp public static class LogTestServiceTestMockUp extends MockUp<LogTestService> { 
    @Mock private String privateTest(String str) { 
    return "mock private method"; } @Mock final String finalTest(String str) { 
    return "mock final method"; } } public static class DataUtilsMockUp extends MockUp<DataUtils> { 
    @Mock public static boolean isEmptyList(List list) { 
    return false; } } @Test void testTest() throws Exception { 
    new LogTestServiceTestMockUp(); new DataUtilsMockUp(); logTestService.test(); } } 

六、项目依赖

 
    <dependency> <groupId>org.mockito 
     groupId> <artifactId>mockito-core 
      artifactId> <version>3.11.2 
       version> <scope>test 
        scope>  
         dependency> <dependency> <groupId>org.mockito 
          groupId> <artifactId>mockito-all 
           artifactId> <version>1.10.19 
            version> <scope>test 
             scope>  
              dependency>  
              <dependency> <groupId>org.junit.platform 
               groupId> <artifactId>junit-platform-commons 
                artifactId> <version>1.8.2 
                 version> 
                  
                  dependency> <dependency> <groupId>org.junit.platform 
                   groupId> <artifactId>junit-platform-launcher 
                    artifactId> <version>1.8.2 
                     version> 
                     <scope>test 
                      scope> <exclusions> <exclusion> <groupId>org.junit.platform 
                       groupId> <artifactId>junit-platform-commons 
                        artifactId>  
                         exclusion>  
                          exclusions>  
                           dependency>  
                           <dependency> <groupId>org.jmockit 
                            groupId> <artifactId>jmockit 
                             artifactId> <version>1.36 
                              version> <scope>test 
                               scope>  
                                dependency> 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220365.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午8:40
下一篇 2026年3月17日 下午8:40


相关推荐

  • golang 2021.11 激活码【2021免费激活】「建议收藏」

    (golang 2021.11 激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html2JTX0APX6F-eyJsa…

    2022年3月29日
    93
  • mysql sql宽字节注入_SQL注入之宽字节注入

    mysql sql宽字节注入_SQL注入之宽字节注入AboutSQLInje 宽字节注入 0x01 前言对于 SQL 注入 我估计搞安全的都玩的滚瓜烂熟了 搞站什么的都是分分钟来的 但是之前做了一道宽字节注入的题目 又打开了我一扇通往新世界的大门 PS 早都碰到过 只不过一直没有时间写 0x02 宽字节和 mysql 单字节字符集 所有的字符都使用一个字节来表示 比如 ASCII 编码 多字节字符集 在多字节字符集中 一部分字节用多个字节来

    2026年3月16日
    1
  • 大数据_01【介绍】

    大数据_01【介绍】大数据_01【介绍】大数据特点大数据能做什么【海量数据背景下】大数据行业的应用大数据发展前景大数据部门组织结构什么是大数据 指数据集的大小超过了现有典型数据库软件和工具的处理能力的数据大数据特点海量化 数据量从TB到PB多样化 数据类型复杂,超过百分之八十是非结构化的[结构化数据半结构化数据完全非结构化数据]快速化 数据量在持续增加(两位数的增长率),数据处理速度要求高高价值 在海量多样数据的快速分析下能发挥出更高的数据价值大数据能

    2022年5月10日
    43
  • yum 卸载java_linux下安装、卸载java「建议收藏」

    yum 卸载java_linux下安装、卸载java「建议收藏」安装java:1.下载jdk:在http://www.oracle.com/technetwork/java/javase/downloads/java-archive-downloads-javase7-521261.html上下载java安装包jdk-7u51-linux-i586.tar.gz,放入目录/home/lx/download。2.解压缩:[root@centos-lx/]#…

    2025年6月29日
    5
  • 小程序管理后台的基本操作

    小程序管理后台的基本操作文章目录引言 I 公众号和小程序打通 II 基础管理 2 1 版本管理 2 2 代码仓库存储 2 3 配置服务器信息 III 云开发 seealso 引言公众号和小程序打通版本管理成员管理管理员 1 人 是注册账号的微信用户 项目成员 15 人 可以登录小程序管理后台 开发者必须是项目成员 体验成员 15 人 只有体验的权限 没有开发的权限 开发管理 服务器域名配置 Request 地址 就是 api 的 baseURL 本地开发时可以关闭 https 验证 上线时一定要小程序管理后台中添加上

    2026年3月19日
    2
  • linux idea2021.4 激活码_通用破解码

    linux idea2021.4 激活码_通用破解码,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月16日
    374

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号