flyway+junit5做集成测试、单元测试

适用场景

  • 功能开发完成后,后端开发人员进行代码自测
  • 代码重构后,集成测试

一些注解

  • 相关源码包: junit-jupiter-api
annotationsdescription
@Test用例
@ParameterizedTest参数化用例
@DisplayName标识用例的名称
@BeforeEach每个用例运行之前操作
@AfterEach每个用例运行之后操作
@BeforeAll本类的每个用例运行之前操作
@AfterAll本类的每个用例运行之前操作
@Nested标识为嵌套用例集合,该标识下,@BeforeAll与AfterAll,仅运行一次

Getting Started

场景一

  • 我要测试一个dao的sql是否写的正确
// 声明一个测试类
@SpringBootTest
@TestPropertySource("classpath:application-test.properties")
public class ExampleTestApplicationTests {
    @Autowired
    private UserInfoDao userInfoDao;

    // 声明一个测试函数
    @Test
    @DisplayName("用例: 用户更新")
    public void updateUserInfo() {
       UserInfo userInfo = UserInfo.builder().id(1L).userName("香槟").build();

       int result = userInfoDao.updateById(userInfo);

       Assertions.assertEquals(1,result);
    }
}

场景二

  • 测试接口异常
  • 通过Assertions.assertThrows(…)来断言,获取异常
  • JdbcTestUtil2是我针对JdbcTestUtil自己扩展的,用来准备数据、校验数据;这里准备数据与校验数据不直接用dao的原因(测试场景脱离业务代码,防止业务dao语句存在问题而影响测试结果)
    @Test
    public void registerDuplicate() {
        String prepareStatement = "INSERT INTO `user_info` (`id`, `user_name`) VALUES ('101', '香槟')";
        int prepareRows = JdbcTestUtil2.updateTable(jdbcTemplate, prepareStatement);
        Assertions.assertEquals(1, prepareRows);

        DataIntegrityViolationException exception = Assertions.assertThrows(DataIntegrityViolationException.class, () -> {
            userInfoService.register("香槟");
        });
        Throwable rootCause = Optional.ofNullable(ExceptionUtils.getRootCause(exception)).orElse(exception);
        Assertions.assertEquals("Duplicate entry '香槟' for key 'idx_uinfo_uname'", rootCause.getMessage());
    }

场景三

  • 测试下Controller接口
  • mockMvc是针对DispatcherServlet进行操作的,这就需要我们手动添加一些filters,这与interrupter不同

    @Autowired
    private WebApplicationContext webApplicationContext;

    public MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .addFilters(webApplicationContext.getBean(LoggerFilter.class))
            .build();

    @Test
    @DisplayName("注册成功")
    public void registerSuccess() throws Exception {
        MvcResult mvcResult = mockMvc.perform(
                        MockMvcRequestBuilders.get("/api/user/register")
                                .header("traceId", "123456")
                                .param("userName", "香槟"))
                .andExpect(MockMvcResultMatchers.status().is2xxSuccessful())
                .andReturn();
        String responseStr = mvcResult.getResponse().getContentAsString();
        BaseResult<Object> baseResult = objectMapper.readValue(responseStr, new TypeReference<BaseResult<Object>>() {
        });
        Assertions.assertEquals("success", baseResult.getCode());
    }

场景四

  • 接口入参条件不同,返回的结果是相同的,这时候写多个@Test函数,会造成代码重复性较高,也不利维护
  • 引入 @ParameterizedTest 参数化用例,该注解仅适用于同返回结果,Assertions…相同场景
    @ParameterizedTest
    @CsvSource({
            "'99999899',123456",
            "'99999899',dfadfdf",
            "'99999899',0000000",
    })
    public void userInfoModify(ArgumentsAccessor arguments) throws Exception {
        UserInfoModifyCommand build = UserInfoModifyCommand.builder()
                .oldPassword((String) arguments.get(0))
                .password((String) arguments.get(1))
                .build();

         // .......
    }

场景五

  • 用例归类;往往我们一个Controller/Bean的Method有多个场景需要测试,这时候如果在idea-structure里会看到几十个的method,非常不利于阅读
  • 引入 @Nested 、内部类
  @Nested
  @DisplayName("注册")
  class registerTest {

      @Test
      @DisplayName("注册成功")  
      public void registerSuccess(){
        // ......
      }

      @Test
      @DisplayName("重复注册")
      public void registerDuplicate(){
        // ......
      }
  } 

在这里插入图片描述

场景六

  • 每个测试用例的数据需要隔离; 所以我们可以在执行用例前,清一下表数据
  • show tables; => TableName.getAllTableNames()
    @BeforeEach
    public void cleanTable() {
        JdbcTestUtils.deleteFromTables(jdbcTemplate, TableName.getAllTableNames());
    }

场景七

  • 外部渠道、中间件由于存在不稳定性及依赖关系,我们需要对相关的API进行Mock
    mockito

    // mock下 userDao
    @MockBean
    private UserDao userDao;
 
    @Test
    @DisplayName("用例: 注册成功")
    public void registerSuccess() {
      
        Mockito.when(userDao.save(Mockito.any()))
                .thenReturn(UserInfo.builder().userName("小西").build());

        Mockito.when(userDao.save(Mockito.any())).thenThrow(new IllegalArgumentException("异常"));

        // ....... do something
    }

场景八

        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值