去年產品剛開始開發時,使用 @SpringBootTest 去測試全部 Mapper 的總時間都還在可以接受的範圍。 今年年初由於產品功能慢慢變多,使用 @SpringBootTest 去測試全部 Mapper 的總時間越拉越長,於是開始研究降低總時間的方式。 研究的過程中,發現 MyBatis 其實自己有出測試框架,只要在測試中把 @SpringBootTest 換成 @MyBatisTest,就可以大幅降低執行時間,因為 @MyBatisTest 不會像 @SpringBootTest 一樣要準備所有 context。 想針對 Mapper 做純單元測試,只要做到啟動 H2 及取得 Mapper,不需要啟動 Spring Container的 Mapper 純單元測試:使用 SqlSessionFactory! 数据脚本 schema.sql data.sql 工具类 测试 当使用MyBatis时,Configuration 和 Environment 是两个重要的概念,它们之间存在特定的关系,用于配置和管理数据库连接等运行环境。 Configuration(配置): Configuration 类是MyBatis的核心配置类,负责管理所有配置信息,包括数据库连接、映射关系、插件等。每个Configuration对象对应一个MyBatis配置,通过此对象,可以访问和修改各项配置。 Environment(环境): Environment 类代表MyBatis的运行环境,包括数据库连接信息和事务管理器等。每个Environment对象关联一个数据库连接池(DataSource)和一个事务管理器(TransactionFactory)。 两者之间的关系如下: 每个Configuration对象可以与一个或多个Environment对象关联,表示MyBatis可以在不同环境中运行,例如开发、测试、生产等。 每个Environment对象包含数据库连接池和事务管理器。数据库连接池(DataSource)用于获取连接,事务管理器(TransactionFactory)用于管理事务。每个Environment对象可以配置一个数据库连接池和一个事务管理器,确保正确管理连接和事务。 在MyBatis的配置文件中,您可以使用以下方式配置Environment: 在上述配置中,通过 总而言之,Configuration是MyBatis的总体配置管理类,而Environment是定义数据库连接和事务管理的环境配置类。您可以根据需求配置多个Environment,然后在Configuration中选择适合的环境来运行。第一階段:@SpringBootTest
第二階段:@MyBatisTest
第三階段:SqlSessionFactory
CREATE TABLE cars(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(150), price INT);
INSERT INTO cars(name, price) VALUES('Audi', 52642);
INSERT INTO cars(name, price) VALUES('Mercedes', 57127);
INSERT INTO cars(name, price) VALUES('Skoda', 9000);
INSERT INTO cars(name, price) VALUES('Volvo', 29000);
INSERT INTO cars(name, price) VALUES('Bentley', 350000);
INSERT INTO cars(name, price) VALUES('Citroen', 21000);
INSERT INTO cars(name, price) VALUES('Hummer', 41400);
INSERT INTO cars(name, price) VALUES('Volkswagen', 21600);
MybatisFactoryimport java.util.List;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
/**
* 构建mybatis测试环境
*/
public class MybatisFactory {
/**
* h2 数据源构建
*/
EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
/**
* 添加启动脚本
*
* @param script
*/
public void addInitScript(String script) {
embeddedDatabaseBuilder.addScript(script);
}
public MybatisFactory() {
// h2 数据源构建
embeddedDatabaseBuilder
.setType(EmbeddedDatabaseType.H2)
.setName("test");
}
public <T> SqlSessionFactory getSqlSessionFactory(List<Class<T>> mappers) {
Environment environment =
new Environment("development", new JdbcTransactionFactory(), embeddedDatabaseBuilder.build());
Configuration configuration = new Configuration(environment);
for (Class<T> mapper : mappers) {
configuration.addMapper(mapper);
}
return new SqlSessionFactoryBuilder().build(configuration);
}
}
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
public class FactoryTest {
@Test
public void testCar() {
MybatisFactory mybatisFactory = new MybatisFactory();
mybatisFactory.addInitScript("db/schema.sql");
mybatisFactory.addInitScript("db/data.sql");
SqlSessionFactory sqlSessionFactory = mybatisFactory.getSqlSessionFactory(List.of(CarMapper.class));
try (SqlSession session = sqlSessionFactory.openSession()) {
CarMapper carMapper = session.getMapper(CarMapper.class);
Car car = carMapper.getCarByName("Audi");
assert car.getPrice() == 52642;
}
}
}
Configuration 和 Environment
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
参考