图文

正经人谁写 Junit 啊!

开发流程
文章目录4 节

前言

开发流程

这也太敏捷了

你的单元测试呢?

测了几个功能?

代码覆盖率多少?

哦,你说这些啊,我从来不写单元测试!

正经人谁写 Junit 啊!正文示意图 2

惊!你这单元测试的姿势都不对,就和打王者一样,同样是玩游戏,有人躺着,有人跪着……

来,赶紧过来跟着我看看单元测试!

项目分层

一般开发过程中,都是要对项目进行分层的,先来看看阿里巴巴 Java 开发手册中,是如何对项目进行分层的?

Java 开发手册

当然实际工作中不可能是这样的,再来看看我一般使用的分层:

差不多这样吧!

单元测试

至于单元测试,一般情况下,是很少写。(除非无奈,一般人都不写吧!)

不会吧!不会吧!还有人写单元测试,单元测试不就是为了代码扫描的时候通过一下嘛?

其实,单元测试是有要求的!

正经人谁写 Junit 啊!正文示意图 5

在 IDEA 中 clean install 时,也会执行 maven 的 test 插件,运行一遍所有的 junit。

正经人谁写 Junit 啊!正文示意图 6

当然,如果希望执行 test 可以点击

正经人谁写 Junit 啊!正文示意图 7

或者执行命令:

正经人谁写 Junit 啊!正文示意图 8

忽略掉测试即可。

也有其他的方法忽略测试,比如配置 <skipTests>true</skipTests> 或 <maven.test.skip>true</maven.test.skip>。

总之,单元测试是会在打包的时候自动执行,也可以忽略。并且单元测试要允许重复执行。

不能说我今天执行成功,第二天执行失败。

具体可以在阿里巴巴 Java 开发手册单元测试章节已经说明很多了。

正经人谁写 Junit 啊!正文示意图 9

至此,都是为了说明一个道理,单元测试很重要!

正经人谁写 Junit 啊!正文示意图 10

下面来看看单元测试的使用姿势!

单元测试的使用

既然对项目进行了分层,那肯定要每一层都要测试到。所以就一起看看我最近学到的单元测试的新知识!

IDEA 快捷创建单元测试

在开始之前,先说下 IDEA 的快捷键,有助于提高开发效率。

  1. ⌥ + ⏎ (Option + Enter)

正经人谁写 Junit 啊!正文示意图 11

  1. ⌘ + N

正经人谁写 Junit 啊!正文示意图 12

快捷创建 Junit 测试类。

正经人谁写 Junit 啊!正文示意图 13

姿势一:Dao 层测试

需要注解:

  • @Transactional
  • @Rollback
  • @Sql

比如呢?我想测试插入用户。

@Slf4j
@Rollback
@Transactional
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebApplication.class)
public class UserMapperTest {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    @Sql(statements = "delete from user_info")
    public void insertUser() throws CustomException {

        // 创建 userInfo 对象, 都是伪代码!
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId("1000001");
        userInfo.setUserName("liuzhihang");

        userInfoMapper.insertUserInfo(userInfo);

        UserInfo record = userInfoMapper.selectById("1000001");

        Assert.assertNotNull(record);

    }
}
  1. @Sql(statements = "delete from user_info") 注解,保证 junit 执行之前,把表清了;
  2. 先插入再查询,Assert 断言结果是否 OK;
  3. @Rollback、@Transactional 保证 junit 执行结束回滚。

姿势二:Service 层测试

需要注解

  • @MockBean
@Slf4j
@Rollback
@SpringBootTest(classes = WebApplication.class)
public class UserServiceTest {

    @MockBean
    private UserInfoMapper userInfoMapper;

    @Autowired
    private UserInfoService userInfoService;

    @Test
    public void insertUser() throws CustomException {

        // 创建 userInfo 对象, 都是伪代码!
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId("1000001");
        userInfo.setUserName("liuzhihang");

        Mockito.when(userInfoMapper.selectById("1000001")).thenReturn(userInfo);
        
        UserInfoRespDTO respDTO = userInfoService.queryUserInfo("1000001");

        Assert.assertNotNull(respDTO);

    }
}

意思到了就行,细节不重要。

核心姿势:

  1. @MockBean
  2. Mockito.when().thenReturn();

这样可以在 service 方法中调用到其他组件的某个方法的时候,mock 一个返回数据。比如:

  1. Mock Mapper 层的返回结果;
  2. Mock 远端的返回结果。

Mock 远程调用时,需要使用门面模式把远程 Dubbo 接口或者 Http 接口进行包装,然后 mock 自己的门面即可。

姿势三:Controller 层测试

这个就简单了,直接项目起起来,然后一个 Postman,一切结束。

其实,并不然。

需要注解:

  • @WebMvcTest
  • @MockBean

需要注入对象:

  • MockMvc
@WebMvcTest(UserInfoController.class)
public class UserInfoControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserInfoService userInfoService;

    @Test
    public void queryUserInfo() throws CustomException {

        // 创建 userInfo 对象, 都是伪代码!
        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setUserId("1000001");
        userInfoDTO.setUserName("liuzhihang");

        Mockito.when(userInfoService.queryUserInfo("1000001")).thenReturn(userInfoDTO);

        mockMvc.perform(post("/user/queryUserInfo")
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .content(JSON.toJSONString(reqVO)))
                .andDo(print())
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.code").value("00000"))
                .andReturn()
                .getResponse()
                .getContentAsString();
    }
}

核心姿势:

  1. @MockBean
  2. Mockito.when().thenReturn();
  3. MockMvc
  4. mockMvc.perform……

调用 service 时,mock 一份 service 返回的 DTO,然后使用 mockMvc 对象请求接口并校验返回。

姿势四:使用断言

除了上面介绍的注解之外,还需要注意 Assert 断言的使用。

正经人谁写 Junit 啊!正文示意图 14

一般情况下默认的 Assert 就可以满足使用,当然复杂情况的断言可以使用 Mockito 框架提供的断言。

具体姿势,就看看官方文档吧!

总结

本文简单介绍了为什么要使用 junit,以及如何使用 junit 对工程的各个分层进行测试。

心动不如行动。

赶紧去试试吧!

相关推荐

打开原图

订阅更新,继续阅读新的实践记录

最近发布

评论

隐私提示

昵称、网址和评论内容会公开显示,邮箱不公开。请勿在评论中填写敏感信息。