Spring Boot测试报错java.lang.IllegalStateException问题排查求助
先看你抛出的错误栈,最核心的问题是:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
这说明Spring容器没法创建entityManagerFactory这个Bean,进而导致依赖它的productsRepository初始化失败。我帮你梳理几个关键问题和对应的解决办法:
1. 测试类指定了错误的启动类
你的测试类里写了:
@SpringBootTest(classes = ApplicationTest.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
但ApplicationTest只是一个空的测试类,不是你的Spring Boot主启动类(也就是带@SpringBootApplication注解的那个类)。Spring Boot测试需要加载主启动类来扫描所有组件(Repository、Controller、Service等)并完成自动配置,比如JPA的entityManagerFactory就是自动配置的一部分。
解决方法:
- 找到你项目里带
@SpringBootApplication的主类(比如叫Application或者FruitShopApplication),把它替换到classes参数里; - 如果主类和测试类在同一个包或者子包下,甚至可以省略
classes参数,Spring会自动扫描找到主启动类。
修改后的测试类注解:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) // 如果主类不在同一包,就加上classes = 你的主启动类.class public class ProductsControllerTest { // ... 原有代码 }
2. 手动引入Hibernate依赖导致冲突
你的pom.xml里手动加了hibernate-core和hibernate-entitymanager:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.12.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>5.4.12.Final</version> </dependency>
但spring-boot-starter-data-jpa已经包含了这些依赖,并且Spring Boot会管理它们的版本,手动指定版本会破坏自动配置,导致JPA相关的Bean(比如entityManagerFactory)无法正常创建。
解决方法:删除这两个手动引入的Hibernate依赖,只保留spring-boot-starter-data-jpa即可。
3. applicationtest.properties的错误配置
spring.main.web-application-type=none:这个配置会让Spring Boot不启动Web容器,但你的测试用了WebEnvironment.RANDOM_PORT,需要Web环境来启动嵌入式服务器,这个配置会导致矛盾,同时也可能影响JPA自动配置的流程。删除这个配置。spring.profiles.active=@spring.profiles.active@:这个是Maven资源过滤的占位符,如果你的Maven没有配置对应的属性,这个值不会被替换,建议直接注释掉或者设置为具体的环境(比如test),避免配置加载异常。
修改后的applicationtest.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/fruitshop?serverTimezone=UTC spring.datasource.username=root spring.datasource.password=password spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect # spring.profiles.active=test # 改成具体值或者注释掉
4. 控制器接口与测试请求不匹配
你的控制器addNewProduct方法用@RequestParam接收参数:
public @ResponseBody String addNewProduct (@RequestParam (value = "name") String NameOfFruit, @RequestParam (value = "price") int PriceOfProduct)
但测试里是直接传Products对象的JSON:
ResponseEntity<Products> postResponse = restTemplate.postForEntity("/products/addProduct", product, Products.class);
这种情况下,请求参数格式不匹配,即使上下文加载成功,测试也会失败。
解决方法:把控制器的参数改成接收@RequestBody Products product,这样才能正确解析JSON格式的请求体:
@RequestMapping(value = "/addProduct", method = RequestMethod.POST) public @ResponseBody String addNewProduct (@RequestBody Products product) { productsRepository.save(product); return "Done"; }
最后验证步骤
- 确保主启动类上有
@SpringBootApplication注解,并且能正常启动项目; - 按照上面的修改调整测试类、pom.xml、applicationtest.properties和控制器;
- 重新运行测试,应该能正常加载ApplicationContext并执行测试用例。
内容的提问来源于stack exchange,提问作者Asel

