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

如何用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,加快测试启动速度

修复你原有测试的核心要点

  1. 确保Mock实例被注入:你之前创建了Mock但没关联到Shell命令,这是核心问题,上面两种方案都解决了这个点
  2. 修正Verify对象名:你原来的verify(remoteConfigService)是笔误,应该用你定义的remoteService变量

内容的提问来源于stack exchange,提问作者Никита Арсеньев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:08:02