You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:10:31