Spring Boot集成测试SQL脚本路径错误及测试策略疑问
问题解决与测试优化方案
1. 修复脚本读取错误(CannotReadScriptException)
脚本读取失败是因为@Sql注解的路径格式错误,你用了{/resources/schema.sql}的错误写法,正确路径写法有两种:
- 直接写
"/schema.sql"(Spring默认从类路径根目录查找,resources就是类路径根目录) - 显式指定类路径:
"classpath:schema.sql"
修改后的测试方法注解:
@Test @Sql("/schema.sql") void shouldCreatePost() throws Exception { // ... 原有代码 }
另外,无需手动指定@TestExecutionListeners(listeners = { SqlScriptsTestExecutionListener.class }),Spring Boot测试默认已包含该监听器,可以直接删除这个注解。
2. 切换到内存数据库(符合集成测试隔离要求)
你计划用内存数据库做测试,但当前配置的是本地真实MySQL,集成测试应使用内存数据库避免依赖外部环境,推荐用H2:
- 添加H2测试依赖(Maven):
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>
- 在
src/test/resources下创建测试专用配置文件application-test.properties:
spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 spring.datasource.username=sa spring.datasource.password= spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create-drop spring.jpa.defer-datasource-initialization=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect spring.sql.init.mode=always
- 在测试类上添加
@ActiveProfiles("test")启用测试配置:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @ActiveProfiles("test") class OrderServiceApplicationTests { // ... 原有代码 }
3. 修复原生SQL查询的兼容性问题
MySQL不支持FULL JOIN(FULL OUTER JOIN),你的Repository查询中使用该语法会导致执行错误。如果需要全连接逻辑,需用LEFT JOIN + UNION + RIGHT JOIN模拟:
@Query( value = "SELECT order_id,title,description,requirement,salary,user_info.name,user_info.contact,date"+ " FROM job_order " + " LEFT JOIN user_info " + " ON sender_id=user_info.id" + " WHERE order_id= ?1 " + " UNION " + " SELECT order_id,title,description,requirement,salary,user_info.name,user_info.contact,date"+ " FROM job_order " + " RIGHT JOIN user_info " + " ON sender_id=user_info.id" + " WHERE order_id= ?1 ;", nativeQuery = true ) Response singlejob(int order_id);
如果业务只需要关联存在的sender_id对应的user_info,换成LEFT JOIN或INNER JOIN更合理。
4. 优化测试逻辑
当前测试先调用jobRepository.save再POST同一个Job,不符合接口创建数据的业务逻辑,建议调整为:
@Test @Sql("/schema.sql") // 初始化user_info数据 void shouldCreatePost() throws Exception { // 构造未指定order_id的Job(order_id建议由数据库自动生成) JobOrder job = new JobOrder(); job.setTitle("Hiring software engineer"); job.setDescription("responsible for developing and maintaining mobile app"); job.setRequirement("Need to know basic sql springboot,2 years exp"); job.setSalary(234); job.setSender_id(1); // 关联schema.sql中插入的user_info的id String request = objectMapper.writeValueAsString(job); mockMvc.perform(MockMvcRequestBuilders.post("/Job/Joborder") .contentType(MediaType.APPLICATION_JSON) .content(request)) .andExpect(status().is2xxSuccessful()); // 验证数据库中存在该Job Optional<JobOrder> savedJob = jobRepository.findById(1); assertThat(savedJob).isPresent(); assertThat(savedJob.get().getTitle()).isEqualTo("Hiring software engineer"); }
内容的提问来源于stack exchange,提问作者user20112858
相关产品推荐
相关产品推荐

