# 简介 ## 文档的翻译版本 可以阅读 MyBatis-Spring-Boot-Starter-Test 文档的以下翻译版本: <ul class="i18n"> <li class="en"><a href="./../index.html">English</a></li> <li class="zh"><a href="./../zh_CN/index.html">简体中文</a></li> </ul> ## 什么是 MyBatis-Spring-Boot-Starter-Test? MyBatis-Spring-Boot-Starter-Test 为 [MyBatis-Spring-Boot-Starter](http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/) 中的 MyBatis 组件提供测试用例。 使用它你将可以做到: * 可以使用 `@MybatisTest` 单独为 MyBatis 组件进行测试 * 在测试 MyBatis 组件时,可以导入依赖 TheMyBatis-Spring-Boot-Starter-Test 要求以下版本: | MyBatis-Spring-Boot-Starter-Test | Spring Boot | Java | |----------------------------------|---------------|-----------| | **3.0** | 3.0 - 3.4 | 17 或更高 | | **2.3** | 2.7 | 8 或更高 | | **~~2.2 (EOL)~~** | ~~2.5 - 2.7~~ | ~~8 或更高~~ | | **~~2.1 (EOL)~~** | ~~2.1 - 2.4~~ | ~~8 或更高~~ | | **~~2.0 (EOL)~~** | ~~2.0 或 2.1~~ | ~~8 或更高~~ | | **~~1.3 (EOL)~~** | ~~1.5~~ | ~~6 或更高~~ | | **~~1.2 (EOL)~~** | ~~1.4~~ | ~~6 或更高~~ | ## 安装 ### Maven 如果你使用 Maven,只需要将下面的依赖放入你的 `pom.xml`: ```xml <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter-test</artifactId> <version>${project.version}</version> <scope>test</scope> </dependency> ``` ### Gradle 如果使用 Gradle,在 `build.gradle` 中加入以下内容: ```groovy dependencies { testImplementation("org.mybatis.spring.boot:mybatis-spring-boot-starter-test:${project.version}") } ``` ## 使用 @MybatisTest 当你想对 MyBatis 组件进行测试时,可以使用 `@MybatisTest` (Mapper 接口与 `SqlSession`)。 默认情况下, 它将会配置 MyBatis(MyBatis-Spring)组件(`SqlSessionFactory` 与 `SqlSessionTemplate`),配置 MyBatis mapper 接口和内存中的内嵌的数据库。 MyBatis 测试默认情况下基于事务,且在测试的结尾进行回滚。 更多相关的信息可参见 [Spring 参考文档](https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-tx-enabling-transactions) 。 再者,普遍情况下 `@Component` beans 将不会被载入 `ApplicationContext` 。 ### 对 Mapper 接口进行测试 如果你想对下面的 Mapper 接口进行测试,你只需要将 `@MybatisTest` 添加在测试类上。 Mapper 接口: ```java package sample.mybatis.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import sample.mybatis.domain.City; @Mapper public interface CityMapper { @Select("SELECT * FROM CITY WHERE state = #{state}") City findByState(@Param("state") String state); } ``` 测试类: ```java package sample.mybatis.mapper; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; import sample.mybatis.domain.City; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.junit4.SpringRunner; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @MybatisTest public class CityMapperTest { @Autowired private CityMapper cityMapper; @Test public void findByStateTest() { City city = cityMapper.findByState("CA"); assertThat(city.getName()).isEqualTo("San Francisco"); assertThat(city.getState()).isEqualTo("CA"); assertThat(city.getCountry()).isEqualTo("US"); } } ``` ### DAO 模式下的测试 如果你为下面的 DAO 类创建测试,你只需要将 `@MybatisTest` 和 `@Import` 添加在你的测试类上。 DAO 类: ```java package sample.mybatis.dao; import org.apache.ibatis.session.SqlSession; import sample.mybatis.domain.City; import org.springframework.stereotype.Component; @Component public class CityDao { private final SqlSession sqlSession; public CityDao(SqlSession sqlSession) { this.sqlSession = sqlSession; } public City selectCityById(long id) { return this.sqlSession.selectOne("selectCityById", id); } } ``` 测试类: ```java package sample.mybatis.dao; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.mybatis.spring.boot.test.autoconfigure.MybatisTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit4.SpringRunner; import sample.mybatis.domain.City; import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @MybatisTest @Import(CityDao.class) public class CityDaoTest { @Autowired private CityDao cityDao; @Test public void selectCityByIdTest() { City city = cityDao.selectCityById(1); assertThat(city.getName()).isEqualTo("San Francisco"); assertThat(city.getState()).isEqualTo("CA"); assertThat(city.getCountry()).isEqualTo("US"); } } ``` ## 使用真实的数据库 内嵌的数据库通常在测试上表现良好,因为们很快,且不需要安装一些开发工具。 然而如果你希望使用真实的数据库,你可以像下面这样使用 `@AutoConfigureTestDatabase` : ```java package sample.mybatis.mapper; // ... import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; @RunWith(SpringRunner.class) @MybatisTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class CityMapperTest { // ... } ``` ## 避免探测到真实的 @SpringBootApplication `@MybatisTest` 在默认情况下将会探测到带有 `@SpringBootApplication` 的类。 因此,由于 bean 定义的一些方法,可能会发生一些意想不到的错误,或者一些不必要的组件被装入 `ApplicationContext` 。 为了避免这种情况,我们可以在与测试类相同的包中创建带有 `@SpringBootApplication` 的类。 ```java package sample.mybatis.mapper; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication class MapperTestApplication { } ``` ## 与其他 @***Test 一起使用 如果 `@MybatisTest` 与其他的 `@***Test` 一起使用(例如: `@WebMvcTest`), 请考虑使用 `@AutoConfigureMybatis` ,因为不能在同一测试中指定两个或多个`@***Test` 注解。 测试的目标类: ```java @RestController public class PingController { PingMapper mapper; PingController(PingMapper mapper) { this.mapper = mapper; } @GetMapping("ping") String ping() { return mapper.ping(); } } ``` ```java @Mapper public interface PingMapper { @Select("SELECT 'OK'") String ping(); } ``` 测试类: ```java @RunWith(SpringRunner.class) @WebMvcTest @AutoConfigureMybatis // 替代 @MybatisTest public class PingTests { @Autowired private MockMvc mvc; @Test public void ping() throws Exception { this.mvc.perform(get("/ping")) .andExpect(status().isOk()) .andExpect(content().string("OK")); } } ``` ## 在 JUnit 5 上使用 @MybatisTest `@MybatisTest` 可以在 JUnit 5 上使用: ```java @ExtendWith(SpringExtension.class) @MybatisTest public class CityMapperTest { // ... } ``` 自 2.0.1 起, `@ExtendWith(SpringExtension.class)` 可以像下面这样被忽略: ```java @MybatisTest public class CityMapperTest { // ... } ``` ## 附录 ### 导入的自动配置 `@MybatisTest` 将会导入以下自动配置的类: * `org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration` * `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` * `org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration` * `org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration` * `org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration` ### 可运行的样例 项目(为每个类型)提供了两个样例供使用: | 分类 | 样例 | 描述 | |:------ |:----------------------------------------------------------------------------------------------------------------------------------- |:--------------------------------------------------------------------- | | 核心 | [样例1](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-annotation) | 展示了最简单的场景,只有一个 mapper 和一个注入 mapper 的组件。这就是我们在“快速入门”部分看到的例子。 | | | [样例2](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-xml) | 展示了如何在 XML 文件中使用一个带有语句的 Mapper,并且也有使用 `SqlSessionTemplate` 的 DAO 的示例。 | | JVM 语言 | [样例3](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-kotlin) | 展示了如何和 kotlin 一同使用。 | | | [样例4](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-groovy) | 展示了如何和 groovy 一同使用。 |