Spring测试中@Sql注解失效问题排查求助
我之前也碰到过一模一样的情况——用@DataJpaTest时data.sql能正常加载,但专门指定@Sql脚本却死活不生效。下面是我踩坑后总结的排查和解决方法:
1. 先确认@Sql的路径是否正确
这是最常见的问题!@Sql默认是相对于测试类的包路径来查找脚本的,如果你把SQL文件放在src/test/resources根目录下,必须用绝对路径指定:
// 正确写法:用classpath前缀或者直接以/开头 @Sql("classpath:/test-specific-data.sql") // 或者更简洁的写法(Spring会自动识别classpath) @Sql("/test-specific-data.sql")
举个例子:如果你的测试类在com.example.repositorytest包下,而SQL文件在resources/sql/test-data.sql,那路径要写成@Sql("/sql/test-data.sql")。
2. 检查事务回滚导致的“假失效”
@DataJpaTest默认会给测试方法加上@Transactional,测试结束后会自动回滚事务。如果你的@Sql脚本是在测试事务内执行的,脚本插入的数据会跟着事务一起回滚,导致你在测试里看不到数据。
解决方法是让脚本在独立事务中执行:
@Sql( scripts = "/test-specific-data.sql", config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED) )
这样脚本会在单独的事务里运行,不会被测试的回滚影响。
3. 排除默认data.sql的干扰
如果你同时存在data.sql,它会被@DataJpaTest自动加载,可能和你的@Sql脚本冲突,或者覆盖你想要的初始化数据。如果只想让@Sql脚本生效,可以禁用默认的data加载:
@DataJpaTest @TestPropertySource(properties = { "spring.sql.init.data-locations=none" // 关闭默认data.sql加载 }) @Sql("/test-specific-data.sql") public class MyRepoTest { // ... }
4. 查看日志排查执行细节
如果上面的方法都没用,开启日志看看脚本到底有没有被加载执行。在src/test/resources/application-test.properties里添加:
logging.level.org.springframework.jdbc.datasource.init=DEBUG logging.level.org.springframework.test.context.jdbc=DEBUG
运行测试后,你可以在日志里看到:
- 脚本是否被找到
- 执行过程中有没有SQL语法错误
- 脚本执行的时机是否符合预期
5. 确认@Sql的执行时机
默认@Sql是在测试方法执行前运行(BEFORE_TEST_METHOD),如果你的测试逻辑需要在其他时机加载数据,可以调整executionPhase:
// 在测试类初始化前执行脚本 @Sql( scripts = "/test-data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS )
示例完整代码
@DataJpaTest @TestPropertySource(properties = { "spring.sql.init.data-locations=none" }) @Sql( scripts = "/test-specific-data.sql", config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED) ) public class UserRepositoryTest { @Autowired private UserRepository userRepository; @Test void shouldFindUserFromSqlScript() { Optional<User> user = userRepository.findByUsername("test-user"); assertThat(user).isPresent(); } }
内容的提问来源于stack exchange,提问作者Jonathan

