1. 程式人生 > 程式設計 >Springboot Mybatis-Plus資料庫單元測試實戰(三種方式)

Springboot Mybatis-Plus資料庫單元測試實戰(三種方式)

  單元測試長久以來是熱門話題,本文不會討論需不需要寫單測,可以看看參考資料1,我個人認為寫好單測應該是每個優秀開發者必備的技能,關於寫單測的好處在這裡我就不展開討論了,快速進入本文著重討論的話題,如何寫好資料庫單測。

  為什麼要寫資料庫單測? 相信大家是不是有這樣類似的經歷,在寫完複雜的sql語句後,自信滿滿的提測,發現很大一部分Bug都是因為sql語句出現問題了,要麼少寫逗號,要麼漏了欄位,悔不當初哇,為啥寫完不多測測呢!

  沒關係!這就教你如何寫資料庫單測,讓你輕鬆告別資料庫相關bug。

1. 資料庫樣例和環境

  我們以使用者表為例開啟本次教程:

使用者表

圖1.1 使用者表ER圖

  引入mybatis-plus外掛後,mapper類如下:

@Mapper
public interface UserMapper extends BaseMapper<UserDO> {
}

  整體環境:

  • spring boot: 1.5.18.RELEASE
  • mybatis: 3.5.1
  • mybatis plus:3.4.0(此時最新版本,我們會用到最新版本的特性)

  在這裡我們直接測試的是mybatis plus提供的一些CRUD,當然這些CRUD一般都不會錯,實際專案中我們只需對自定義的SQL進行單元測試即可。

2. 方式一:啟動整個環境

  這種方式應該是日常環境使用最多的,利用SpringBoot自1.4.0版本開始引入的@SpringBootTest註解可以啟動我們單元測試所需要的所有環境,當然,如果你專案中運用了其他分散式服務,他同樣也會啟動這些服務。單測程式碼如下:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {

  @Autowired
  private UserMapper userMapper;

  @Test
  public void testCurd() {
    UserDO userDO = new UserDO();
    userDO.setId(7777L);
    userDO.setGmtModified(new Date());
    userDO.setGmtCreate(new Date());
    userDO.setRealName("ke");
    userDO.setUserName("ni");
    userMapper.insert(userDO);

    UserDO select = userMapper.selectById(1);
    System.out.println(select);
  }
}

@SpringBootTest註解可以設定需要啟動載入的類,按需載入

3. 方式二:只啟動資料庫環境+遠端資料庫

  在參考資料2中,最新的mybatis-plus釋出版本(3.4.0)中引入了test starter,如圖:

Mybatis-plus3.4.0新特性

圖3.1 Mybatis-plus3.4.0引入test模組

  模組引入了新的註解@MybatisPlusTest,這個註解可以幫助我們只啟動特定特定的模組,直接上單測程式碼:

@RunWith(SpringRunner.class)
@MybatisPlusTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class UserMapperTest {

  @Autowired
  private UserMapper userMapper;


  @Test
  public void testCurd() {
    UserDO userDO = new UserDO();
    userDO.setId(7777L);
    userDO.setGmtModified(new Date());
    userDO.setGmtCreate(new Date());
    userDO.setRealName("ke");
    userDO.setUserName("ni");
    userMapper.insert(userDO);

    UserDO select = userMapper.selectById(1);
    System.out.println(select);
  }
}

  是不是很輕鬆?不過我們要注意如下幾點關鍵點:

  • @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)的作用是使用自定義的資料來源,而非使用自動配置的嵌入式記憶體資料來源
  • 如果你在專案正在使用類似於druid的連線池,在test模組的時候需要在application配置檔案裡面直接使用jdbc資料來源即可,因為@MybatisPlusTest註解不會啟動連線池框架,典型的配置檔案application.yml如下:
spring:
 datasource:
  url: jdbc:mysql://xxx.xxx.1.110:3306/test?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
  username: root
  password: 123456

4. 方式三:只啟動資料庫環境+本地資料庫

  在方式二的基礎上,進行如下步驟:

  • 我們去掉@AutoConfigureTestDatabas註解,直接啟動測試嵌入式資料庫即可,在這裡我們選用H2記憶體資料庫,首先在pom中引入H2 database maven依賴;
  • 然後後在test環境下引入sechema.sql檔案,這個檔案是用來初始化資料庫的,核心是建立表格語句;
  • 最後去掉這個頁面以後寫法和方式二一樣,在這裡就不給出

注意: sechema.sql檔案要符合嵌入式資料庫的語法,在本例中為h2資料庫,如果你正在使用mysql資料庫,則需要把mysql的資料庫語法轉換為h2的資料庫語法。

5. @MybatisPlusTest註解原理

  如果你之前使用過MyBatis-Spring-Boot-Starter-Test中的@MybatisTest(參考資料3)的話,你會發現@MybatisPlusTest註解原理與之類似,都是限制spring boot的自動配置(參考資料4),只需要載入特定的配置即可。我們來看一下註解原始碼:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(MybatisPlusTestContextBootstrapper.class)
@ExtendWith({SpringExtension.class})
@OverrideAutoConfiguration(
  enabled = false
)
@TypeExcludeFilters({MybatisPlusTypeExcludeFilter.class})
@Transactional
@AutoConfigureCache
@AutoConfigureMybatisPlus
@AutoConfigureTestDatabase
@ImportAutoConfiguration
public @interface MybatisPlusTest {
  String[] properties() default {};

  boolean useDefaultFilters() default true;

  Filter[] includeFilters() default {};

  Filter[] excludeFilters() default {};

  @AliasFor(
    annotation = ImportAutoConfiguration.class,attribute = "exclude"
  )
  Class<?>[] excludeAutoConfiguration() default {};
}

@OverrideAutoConfiguration(enabled = false)是關鍵,它關閉了自動配置,而一般在spring boot專案中enable是開啟的;

@AutoConfigureMybatisPlus註解是自定義註解,這個註解定義了載入所有所需的載入類,在spring.factories裡面聲明瞭要自動配置的類:

# AutoConfigureMybatis auto-configuration imports
com.baomidou.mybatisplus.test.autoconfigure.AutoConfigureMybatisPlus=\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\
com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration

@AutoConfigureTestDatabase註解表明使用的是記憶體資料庫而不是真實資料庫

  有了這些限制和規定以後,mybatis-plus在測試環境內就可以自動載入所需要的的配置了,這樣就去除了非必要資源的載入。

6. 總結

三種資料庫單測總結

圖6.1 三種資料庫單測總結

  如果你正在使用mysql資料庫,我推薦使用方式二。如果你能解決mysq語法轉h2的問題,推薦使用方式三,這樣在離線的情況也可以進行單測,不需要連線遠端資料庫。

PS:如果你有好的工具來完成mysql轉換h2的話可以在評論區裡面推薦一下,我這邊找了好久,包括自定義寫轉換、一些專業工具等,感覺對navicat匯出的語句作轉換不是很好好用。

7.參考資料

[1] 你真的需要單元測試嗎?
[2] Mybatis-Plus釋出版本
[3] MyBatis-Spring-Boot-Starter-Test
[4] SpringBoot四大神器之auto-configuration

到此這篇關於Springboot Mybatis-Plus資料庫單元測試實戰(三種方式)的文章就介紹到這了,更多相關Springboot Mybatis-Plus單元測試內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!