You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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内置统计功能:

  1. 在application-test.yml中开启统计:
spring:
  jpa:
    properties:
      hibernate.generate_statistics: true
  1. 在测试中获取统计数据并断言:
@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 07:17:33