如何为Spring中RabbitListenerEndpointRegistry编写更优JUnit测试
优化RabbitMQ队列启停Controller的JUnit测试方案
我来帮你优化这个RabbitMQ队列启停Controller的JUnit测试,原测试确实有不少可以简化和规范的地方,咱们一步步来调整:
原测试的主要问题
- 用错了测试工具:
MockRestServiceServer是用来测试RestTemplate调用外部服务的,而你的Controller是对外提供接口的,应该用MockMvc来模拟HTTP请求,更贴近真实调用场景。 - 手动管理Controller实例:你自己new了
QueueController,还手动set依赖,其实可以让Spring帮你管理,更符合Spring项目的测试规范。 - 冗余的匿名类实现:手动写
MessageListenerContainer的匿名实现太繁琐,直接用Mockito mock这个接口就好。 - 上下文加载过重:原测试加载了不必要的Bean(比如
ObjectMapper),其实测试Controller只需要加载Web层相关的组件就行。
优化后的测试代码
package com.compnay.depart.rest; import static org.mockito.Mockito.verify; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.amqp.rabbit.listener.MessageListenerContainer; import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry; import org.springframework.test.web.servlet.MockMvc; @WebMvcTest(QueueController.class) public class QueueControllerTest { @Autowired private MockMvc mockMvc; @MockBean private RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry; @MockBean private MessageListenerContainer messageListenerContainer; @Test void testStartEndpoint() throws Exception { // 模拟registry返回我们mock的容器实例 org.mockito.Mockito.when(rabbitListenerEndpointRegistry.getListenerContainer(QueueController.LISTENER_ID)) .thenReturn(messageListenerContainer); // 模拟GET请求,验证响应状态和内容 mockMvc.perform(get("/" + QueueController.LISTENER_ID + "/start")) .andExpect(status().isOk()) .andExpect(content().string("started")); // 关键验证:确保容器的start方法确实被Controller调用了 verify(messageListenerContainer).start(); } @Test void testStopEndpoint() throws Exception { org.mockito.Mockito.when(rabbitListenerEndpointRegistry.getListenerContainer(QueueController.LISTENER_ID)) .thenReturn(messageListenerContainer); mockMvc.perform(get("/" + QueueController.LISTENER_ID + "/stop")) .andExpect(status().isOk()) .andExpect(content().string("stopped")); // 验证stop方法被调用 verify(messageListenerContainer).stop(); } }
优化点说明
- 使用
@WebMvcTest注解:这个注解是Spring Boot专门为测试MVC控制器设计的,只会加载Web层相关的Bean(比如Controller、请求映射器等),测试启动更快,也避免了加载不必要的组件。 - 用
MockMvc模拟HTTP请求:这是测试RestController的标准方式,能模拟真实的HTTP请求,同时可以验证响应状态码、响应内容,比直接调用Controller方法更贴近实际使用场景。 - Mockito自动注入依赖:用
@MockBean注解自动创建并注入mock的RabbitListenerEndpointRegistry和MessageListenerContainer,不需要手动写setter,代码更简洁。 - 增加核心逻辑验证:原测试只验证了返回值,现在通过
verify方法确保Controller确实调用了容器的start/stop方法,测试覆盖更全面。 - 升级到JUnit 5:改用JUnit 5的
@Test注解(不需要加public修饰符),这是当前Java测试的主流框架,功能更丰富。
另外,原Controller里为测试写的getter/setter可以删掉了,因为@WebMvcTest配合@MockBean会自动完成依赖注入,不需要手动管理。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

