JUnit测试中@Autowired依赖注入异常与空指针问题求助
JUnit+Mockito单元测试依赖注入问题解决
问题现象
- 使用
@Autowired配合@SpringBootTest、@ExtendWith(SpringExtension.class)等Spring测试注解时,抛出UnsatisfiedDependencyException,根源是无法解析配置占位符${MASTER_REDIS_SERVER_URL},导致Redis相关Bean创建失败 - 不添加任何Spring测试注解时,所有
@Autowired注入的对象都会触发NullPointerException - 改用Mock对象替代
@Autowired注入,搭配测试注解可正常运行
问题覆盖Controller、Service、Repository各层测试类
解决方案
1. 补充测试环境配置
在src/test/resources目录下创建application-test.properties文件,添加缺失的Redis配置项:
MASTER_REDIS_SERVER_URL=redis://localhost:6379
然后在测试类上指定使用该测试配置:
@SpringBootTest(properties = "spring.profiles.active=test")
2. 排除Redis相关配置类
如果测试不需要Redis功能,直接排除对应的配置类,取消你注释的代码并调整过滤规则:
@ExtendWith(SpringExtension.class) @SpringBootTest @ComponentScan(basePackages = "com.info.payments", excludeFilters = @ComponentScan.Filter( type = FilterType.REGEX, pattern = "com.info.payments.config.*Redis.*" )) class VendorControllerTest { // 原有代码不变 }
3. 用MockBean替代真实依赖
对于不需要真实实例的Bean,用@MockBean替换@Autowired,Spring会自动将容器中的对应Bean替换为Mock对象,避免加载真实依赖:
@ExtendWith(SpringExtension.class) @SpringBootTest class VendorControllerTest { @Autowired VendorController vendorController; @MockBean VendorRepository vendorRepository; @MockBean ModelMapper modelMapper; @BeforeEach void setUp() { // 给Mock设置预期行为,比如让count方法返回0 when(vendorRepository.count()).thenReturn(0L); } @DisplayName("添加或更新供应商") @Test void vendorAddUpdateTest() { VendorRequestDTO vendorRequestDTO = new VendorRequestDTO(); vendorRequestDTO.setGuid(1L); // 给ModelMapper设置Mock转换逻辑 Vendor mockVendor = new Vendor(); mockVendor.setGuid(1L); when(modelMapper.map(vendorRequestDTO, Vendor.class)).thenReturn(mockVendor); // 执行你的测试逻辑 } }
4. Controller层用轻量化测试注解
如果是Controller层测试,推荐使用@WebMvcTest,只会加载Controller相关Bean,无需启动整个Spring上下文,测试速度更快:
@WebMvcTest(VendorController.class) class VendorControllerTest { @Autowired MockMvc mockMvc; @MockBean VendorService vendorService; // 假设Controller依赖该Service @MockBean ModelMapper modelMapper; @Test void vendorAddUpdateTest() throws Exception { VendorRequestDTO vendorRequestDTO = new VendorRequestDTO(); vendorRequestDTO.setGuid(1L); mockMvc.perform(post("/vendors") .contentType(MediaType.APPLICATION_JSON) .content(new ObjectMapper().writeValueAsString(vendorRequestDTO))) .andExpect(status().isOk()); } }
原测试代码
@ExtendWith(SpringExtension.class) @SpringBootTest //@ComponentScan(basePackages = "com.info.payments", // excludeFilters = @ComponentScan.Filter( // type = FilterType.REGEX, // pattern = "com.info.payments.config..*" // )) //@EnableAutoConfiguration @ContextConfiguration(classes = PaymentsInfoApplication.class) class VendorControllerTest { @Autowired VendorController vendorController; @Autowired VendorRepository vendorRepository; @Autowired ModelMapper modelMapper; @BeforeEach void setUp() { if(Objects.nonNull(vendorRepository) && vendorRepository.count() > 0){ vendorRepository.deleteAll(); } } @DisplayName("adding or updating Vendor") @Test void vendorAddUpdateTest() { VendorRequestDTO vendorRequestDTO=new VendorRequestDTO(); vendorRequestDTO.setGuid(1L); Vendor vendorEntityObject = modelMapper.map(vendorRequestDTO, Vendor.class);//here model mapper getting Nullpointer exception. }
依赖注入异常堆栈
Failed to load ApplicationContext java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132) ... Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'MASTER_REDIS_SERVER_URL' in value "${MASTER_REDIS_SERVER_URL}" ...
空指针异常堆栈
java.lang.NullPointerException at com.info.payments.vendor.controller.VendorControllerTest.vendorAddUpdateTest(VendorControllerTest.java:72) ...
内容的提问来源于stack exchange,提问作者naruto
相关产品推荐
相关产品推荐

