如何用Mockito模拟服务?Spring Shell命令测试问题咨询
正确用Mockito模拟Spring Shell命令中的RemoteService服务
你的测试代码目前有两个关键问题:一是你创建的Mock RemoteService没有被注入到Shell命令实例中,导致执行命令时可能调用真实服务;二是verify语句里的对象名写错了(remoteConfigService应该是你定义的remoteService)。下面给你两种靠谱的解决方案,适配不同的测试场景:
方案一:纯Mockito测试(无需启动完整Spring容器)
这种方式适合快速单元测试,不用加载Spring上下文,测试速度更快:
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.shell.Shell; import org.springframework.shell.jline.InteractiveShellApplicationRunner; import org.springframework.shell.jline.ScriptShellApplicationRunner; import java.util.ArrayList; import java.util.List; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; // 让Mockito接管测试类,处理Mock相关注解 @ExtendWith(MockitoExtension.class) public class YourShellCommandTest { // 生成RemoteService的Mock实例 @Mock private RemoteService remoteService; // 自动将Mock的remoteService注入到你的Shell命令类实例中 @InjectMocks private YourShellCommand shellCommand; private Shell shell; // 测试前初始化Shell,禁用交互式运行器避免启动完整交互环境 @BeforeEach void setUp() { shell = Shell.builder() .command(shellCommand) .applicationRunner(InteractiveShellApplicationRunner::DISABLED) .applicationRunner(ScriptShellApplicationRunner::DISABLED) .build(); } @Test public void listCommandTest() { // 预设Mock服务的返回值 List<String> mockEmptyList = new ArrayList<>(); when(remoteService.getAll()).thenReturn(mockEmptyList); // 执行Shell命令 shell.evaluate(() -> "list"); // 验证RemoteService的getAll方法确实被调用了 verify(remoteService).getAll(); } }
关键说明:
@ExtendWith(MockitoExtension.class):启用Mockito的注解支持,自动创建Mock实例并完成注入@InjectMocks:会自动把带有@Mock注解的对象注入到目标Bean(你的Shell命令类)中,适配类中的@Autowired依赖- 初始化Shell时禁用交互式运行器,避免测试时弹出Shell交互窗口
方案二:Spring Boot整合测试(适合需要Spring上下文的场景)
如果你的Shell命令依赖更多Spring组件,需要启动Spring容器,可以用@MockBean直接替换容器中的真实服务:
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.shell.Shell; import java.util.ArrayList; import java.util.List; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; // 只加载Shell命令相关的Bean,减少上下文加载时间 @SpringBootTest(classes = {YourShellCommand.class}) public class YourShellCommandSpringTest { @Autowired private Shell shell; // 用Mock实例替换Spring容器中的RemoteService @MockBean private RemoteService remoteService; @Test public void listCommandTest() { // 预设Mock返回值 List<String> mockEmptyList = new ArrayList<>(); when(remoteService.getAll()).thenReturn(mockEmptyList); // 执行命令 shell.evaluate(() -> "list"); // 验证方法调用 verify(remoteService).getAll(); } }
关键说明:
@MockBean:Spring Boot提供的注解,会自动将容器中原本的RemoteService替换为Mockito的Mock实例,确保Shell命令类注入的是Mock服务@SpringBootTest(classes = {YourShellCommand.class}):指定只加载必要的Bean,加快测试启动速度
修复你原有测试的核心要点
- 确保Mock实例被注入:你之前创建了Mock但没关联到Shell命令,这是核心问题,上面两种方案都解决了这个点
- 修正Verify对象名:你原来的
verify(remoteConfigService)是笔误,应该用你定义的remoteService变量
内容的提问来源于stack exchange,提问作者Никита Арсеньев
相关产品推荐
相关产品推荐

