Spring Boot 3中@WebMvcTest测试报entityManagerFactory缺失错误求助
Spring Boot 3 WebMvcTest 中 JPA Bean 创建失败问题解决
问题背景
使用Spring Boot 3编写UserController的测试类,测试代码如下:
@ExtendWith(SpringExtension.class) @WebMvcTest(value = UserController.class) public class UserConnectionControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserManager userManager; @Test public void retrieveUserConnection() throws Exception{ UserConnection mockUserConnection = new UserConnection(158791, "Paul Smith", "1123977", "01"); mockUserConnection.setDisabled(false); String expected = """ { "userId": 158791, "name": "Paul Smith", "userAccess": "1123977", "userType": "01", "disabled": false } """; Mockito.when(userManager.findByUa(Mockito.anyString())).thenReturn(mockUserConnection); RequestBuilder requestBuilder = MockMvcRequestBuilders.get( "/users/1123977").accept( MediaType.APPLICATION_JSON); MvcResult result = mockMvc.perform(requestBuilder).andReturn(); JSONAssert.assertEquals(expected, result.getResponse() .getContentAsString(), false); } }
错误信息
运行测试时抛出如下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaSharedEM_entityManagerFactory': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument
项目主类配置
项目主类配置如下,实体类和Repository位于依赖jar包的com.acme.common包中:
@SpringBootApplication( scanBasePackages = { "com.acme.extranet", "com.acme.common" } ) @EntityScan("com.acme.common") @EnableJpaRepositories(basePackages = "com.acme.common") public class ExtranetApplication { public static void main(String[] args) { SpringApplication.run(ExtranetApplication.class, args); } }
解决方案
原因分析
@WebMvcTest会自动加载主类的配置,而主类中的@EnableJpaRepositories会触发Spring扫描JPA Repository并初始化JPA相关Bean(如EntityManagerFactory),但测试环境未配置数据库连接等JPA依赖资源,导致Bean创建失败。
方案1:排除JPA相关自动配置类
修改测试类的@WebMvcTest注解,排除JPA相关的自动配置,避免测试上下文加载不必要的JPA组件:
@ExtendWith(SpringExtension.class) @WebMvcTest( value = UserController.class, excludeAutoConfiguration = { JpaRepositoriesAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceAutoConfiguration.class } ) public class UserConnectionControllerTest { // 测试代码不变 }
方案2:改用@SpringBootTest + @AutoConfigureMockMvc
如果排除配置过于繁琐,可使用@SpringBootTest指定MOCK web环境,并配合@AutoConfigureMockMvc,同时保持UserManager的Mock:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) @AutoConfigureMockMvc public class UserConnectionControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserManager userManager; // 测试方法不变 }
方案3:通过@TestConfiguration禁用JPA扫描
在测试类内部添加配置类,移除JPA仓库扫描的Bean定义:
@ExtendWith(SpringExtension.class) @WebMvcTest(value = UserController.class) public class UserConnectionControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserManager userManager; @TestConfiguration static class TestConfig { @Bean public BeanFactoryPostProcessor beanFactoryPostProcessor() { return beanFactory -> beanFactory.removeBeanDefinition("jpaRepositoriesRegistrar"); } } // 测试方法不变 }
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

