Spring Boot单元测试:数据库请求计数方法实现与配置
在Spring Boot中实现数据库请求计数并用于单元测试
一、核心实现思路
通过自定义Hibernate会话监听器统计各类SQL执行次数,再封装断言方法用于单元测试,替代Baeldung示例中的assertSelectCount逻辑。
二、具体配置步骤
1. 自定义SQL计数监听器
创建监听类继承Hibernate的AbstractSessionEventListener,重写方法统计不同类型SQL的执行次数:
public class SqlCountListener extends AbstractSessionEventListener { private final AtomicInteger selectCount = new AtomicInteger(0); private final AtomicInteger insertCount = new AtomicInteger(0); private final AtomicInteger updateCount = new AtomicInteger(0); @Override public void jdbcExecuteStatement(SessionFactoryObserver.SessionFactoryEvent event) { String sql = event.getSqlStatement().trim().toLowerCase(); if (sql.startsWith("select")) { selectCount.incrementAndGet(); } else if (sql.startsWith("insert")) { insertCount.incrementAndGet(); } else if (sql.startsWith("update")) { updateCount.incrementAndGet(); } } // 获取计数的方法 public int getSelectCount() { return selectCount.get(); } // 重置计数器 public void reset() { selectCount.set(0); insertCount.set(0); updateCount.set(0); } }
2. 注册监听器到Spring Boot
在测试环境的配置文件application-test.yml中添加Hibernate监听器配置:
spring: jpa: properties: hibernate.session_factory.event.listeners.jdbc-execute: com.yourpackage.SqlCountListener
或者通过配置类注册(更灵活):
@Configuration @Profile("test") public class TestJpaConfig { @Bean public SqlCountListener sqlCountListener() { return new SqlCountListener(); } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory( DataSource dataSource, JpaVendorAdapter jpaVendorAdapter, SqlCountListener listener) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setJpaVendorAdapter(jpaVendorAdapter); em.setPackagesToScan("com.yourpackage.entity"); Properties props = new Properties(); props.put("hibernate.session_factory.event.listeners.jdbc-execute", listener); em.setJpaProperties(props); return em; } }
3. 封装测试断言方法
编写测试基类,注入监听器并封装断言逻辑:
@SpringBootTest @Transactional public abstract class BaseTest { @Autowired private SqlCountListener sqlCountListener; @BeforeEach void resetSqlCounter() { sqlCountListener.reset(); } protected void assertSelectCount(int expected) { assertEquals(expected, sqlCountListener.getSelectCount()); } protected void assertInsertCount(int expected) { assertEquals(expected, sqlCountListener.getInsertCount()); } }
4. 在单元测试中使用
继承测试基类,直接调用断言方法验证SQL执行次数:
public class UserRepositoryTest extends BaseTest { @Autowired private UserRepository userRepository; @Test void testFindUserById() { // 执行数据库查询操作 User user = userRepository.findById(1L).orElse(null); // 断言SELECT语句执行次数为1 assertSelectCount(1); } @Test void testSaveUser() { User newUser = new User("testUser"); userRepository.save(newUser); // 断言INSERT语句执行次数为1 assertInsertCount(1); } }
三、简易替代方案:利用Hibernate内置统计
如果不想自定义监听器,可直接开启Hibernate内置统计功能:
- 在
application-test.yml中开启统计:
spring: jpa: properties: hibernate.generate_statistics: true
- 在测试中获取统计数据并断言:
@Autowired private EntityManager entityManager; @Test void testSqlCount() { Session session = entityManager.unwrap(Session.class); Statistics stats = session.getSessionFactory().getStatistics(); stats.clear(); // 清空历史统计 // 执行数据库操作 userRepository.findAll(); // 断言查询执行次数 assertEquals(1, stats.getQueryExecutionCount()); }
内容的提问来源于stack exchange,提问作者haoz
相关产品推荐
相关产品推荐

