Spring Boot单元测试:H2库+JdbcTemplate建表填数遇问题
Spring Boot DAO单元测试(H2内存库)解决方案
问题根源
- 使用
@SpringBootTest无限制加载全量应用时,Oracle相关配置/依赖被触发,但测试环境无Oracle驱动,导致DAO报错 - 直接指定
@ContextConfiguration(classes = JdbcTemplate.class)时,Spring无法自动创建JdbcTemplate依赖的DataSource,因此出现空指针
正确实现步骤
1. 配置Test环境H2数据库
在test/resources/application-test.yml中添加H2配置:
spring: datasource: driver-class-name: org.h2.Driver url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 username: sa password:
2. 编写测试专用数据源配置类
创建TestDataSourceConfig,手动配置H2数据源与JdbcTemplate,避免依赖全应用配置:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import javax.sql.DataSource; @Configuration public class TestDataSourceConfig { @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1"); dataSource.setUsername("sa"); dataSource.setPassword(""); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }
3. 编写DAO单元测试类
只加载必要组件(数据源配置、DAO类),激活Test配置,手动初始化测试数据:
import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.assertEquals; @RunWith(SpringRunner.class) @ActiveProfiles("test") @ContextConfiguration(classes = {TestDataSourceConfig.class, YourTargetDao.class}) public class YourTargetDaoTest { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private YourTargetDao targetDao; @Before public void initTestData() { // 创建测试表 jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS user_info (" + "id INT PRIMARY KEY, " + "user_name VARCHAR(255) NOT NULL)"); // 插入测试数据 jdbcTemplate.update("INSERT INTO user_info VALUES (?, ?)", 1, "test_user"); } @Test public void testGetUserNameById() { String userName = targetDao.getUserNameById(1); assertEquals("test_user", userName); } }
4. 确保DAO类的JdbcTemplate注入正确
DAO类需通过构造方法或@Autowired注入JdbcTemplate:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository public class YourTargetDao { private final JdbcTemplate jdbcTemplate; @Autowired public YourTargetDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public String getUserNameById(int id) { return jdbcTemplate.queryForObject( "SELECT user_name FROM user_info WHERE id = ?", String.class, id ); } }
关键说明
- 用
@ContextConfiguration指定仅加载测试必需的类,避免全应用启动带来的Oracle依赖问题 - 手动配置
DataSource解决JdbcTemplate空指针问题 - H2内存库会在测试结束后自动销毁数据,无需手动清理
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

