Jhipster环境下Mock服务始终返回0的RestController测试问题
问题:Mock Service后Controller仍返回0的排查与解决
问题背景
测试一个返回消息计数的RestController方法时,接口始终返回0。已在每次测试运行前Mock Service类,控制器继承JHipster自动生成的父控制器,其中另一个POST方法的测试可正常执行。
控制器代码
@RestController public class MessagesExtResource extends MessagesResource { private final MessagesExtService messagesService; public MessagesExtResource(MessagesExtService messagesService) { super(messagesService); this.messagesService = messagesService; } @GetMapping("/messages/{userId}/count") public ResponseEntity<Integer> messageCount(@PathVariable UUID userId) { int count = messagesService.getMessageCount(userId); return ResponseEntity.ok().body(count); } }
测试类代码
@AutoConfigureMockMvc @WithMockUser @IntegrationTest class MessagesExtResourceTest { private static final UUID DEFAULT_USER_ID = UUID.randomUUID(); private static final String DEFAULT_MESSAGE_URL = "/messages/{userId}"; @Autowired private MockMvc mockMvc; @Autowired private MessagesExtService messagesService; @BeforeEach void setUp() { messagesService = Mockito.mock(MessagesExtService.class); } @Test public void messageCount() throws Exception { //arrange int count = 25; when(messagesService.getMessageCount(DEFAULT_USER_ID)).thenReturn(count); //act mockMvc.perform( get(DEFAULT_MESSAGE_URL + "/count", DEFAULT_USER_ID) .with(csrf()) .contentType(MediaType.APPLICATION_JSON) ) .andDo(print()) .andExpect(status().isOk()) .andExpect(content().string(String.valueOf(count))) //此处报错 ; } }
错误信息
java.lang.AssertionError: 响应内容预期值:<25> 实际值:<0> 预期值 :25 实际值 :0 at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59) at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122) at org.springframework.test.web.servlet.result.ContentResultMatchers.lambda$string$4(ContentResultMatchers.java:148) at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:212) at com.triway.web.rest.v1.MessagesExtResourceTest.unreadMessageCount(MessagesExtResourceTest.java:222) ...(省略后续堆栈信息)
问题原因
测试类中虽然在setUp方法里创建了Mock的MessagesExtService实例,但只是替换了测试类自身的messagesService变量引用,Spring容器中控制器依赖的MessagesExtService实例并没有被替换。控制器调用的还是容器里的原实例,而Mock的行为没有生效,getMesssageCount方法返回int类型的默认值0。
解决方法
使用Spring Boot提供的@MockBean注解替换@Autowired,该注解会自动将Mock对象注入到Spring容器中,替换原有的Bean实例,确保控制器使用的是我们配置了Mock行为的实例。
修改后的测试类:
@AutoConfigureMockMvc @WithMockUser @IntegrationTest class MessagesExtResourceTest { private static final UUID DEFAULT_USER_ID = UUID.randomUUID(); private static final String DEFAULT_MESSAGE_URL = "/messages/{userId}"; @Autowired private MockMvc mockMvc; @MockBean // 替换原来的@Autowired private MessagesExtService messagesService; // 移除原有的setUp方法,@MockBean会自动创建Mock实例 @Test public void messageCount() throws Exception { //arrange int count = 25; when(messagesService.getMessageCount(DEFAULT_USER_ID)).thenReturn(count); //act mockMvc.perform( get(DEFAULT_MESSAGE_URL + "/count", DEFAULT_USER_ID) .with(csrf()) .contentType(MediaType.APPLICATION_JSON) ) .andDo(print()) .andExpect(status().isOk()) .andExpect(content().string(String.valueOf(count))) ; } }
补充说明
如果是单元测试(非集成测试),也可以用@InjectMocks配合@Mock来注入控制器,但因为这里使用了@IntegrationTest(启动Spring容器的集成测试),@MockBean是更合适的方案,能直接管理Spring容器中的Bean实例。
内容的提问来源于stack exchange,提问作者budthapa
相关产品推荐
相关产品推荐

