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

Mockito参数化测试中如何向when传递不同方法调用

解决Mockito参数化测试中动态设置不同方法Stub的问题

你的代码核心问题是:测试类中@Mock的myRepository和TestParameter内部自行mock的MyRepository是两个完全独立的实例,你传递的methodCall是针对内部mock的方法调用,自然不会对测试用的myRepository生效,导致所有用例都返回相同结果。

正确的做法是传递方法调用的逻辑,而不是提前执行方法的结果,可以通过函数式接口来封装不同的Repository方法调用行为:

步骤1:定义函数式接口封装Repository调用

创建一个函数式接口,用来描述对MyRepository的方法调用:

@FunctionalInterface
interface RepositoryCall {
    List<Element> invoke(MyRepository repository);
}

步骤2:修改参数提供类,传递调用逻辑

删除TestParameter内部的多余mock,改为传递封装好的方法调用逻辑:

private static class TestParameter implements ArgumentsProvider {
    @Override
    public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
        return Stream.of(
            // 第一个用例:调用findComponentByKey_1
            Arguments.of(
                Map.of("key_1", "value_2"),
                (RepositoryCall) repo -> repo.findComponentByKey_1(/* 这里传入对应参数 */)
            ),
            // 第二个用例:调用findComponentByKey_2
            Arguments.of(
                Map.of("key_1", "value_2"),
                (RepositoryCall) repo -> repo.findComponentByKey_2(/* 这里传入对应参数 */)
            )
        );
    }
}

步骤3:修改测试方法,动态设置Stub

在测试方法中接收RepositoryCall参数,针对测试类的myRepository实例设置Stub:

@ExtendWith(MockitoExtension.class)
public class MyServiceTest {
    @Mock
    private MyRepository myRepository; // 移除static修饰,不需要静态
    private MyService myService;

    @BeforeEach
    void setUp() {
        myService = new MyService(myRepository);
    }

    @ParameterizedTest
    @ArgumentsSource(TestParameter.class)
    void findAllTest(Map<String, String> allParameters, RepositoryCall repositoryCall) throws JsonProcessingException {
        Element element = Element.builder().identification("id").build();

        // 针对当前测试用的myRepository,执行对应的方法调用并设置Stub
        when(repositoryCall.invoke(myRepository)).thenReturn(List.of(element));

        var actualResponse = myService.execute(allParameters);

        // 执行断言逻辑,比如:
        // assertNotNull(actualResponse);
        // assertEquals(List.of(element), actualResponse);
    }

    // 这里放步骤1的RepositoryCall接口和步骤2的TestParameter类
}

额外注意事项

  • 测试类中的myRepository不需要static修饰,MockitoExtension会为每个测试方法管理mock实例的生命周期。
  • Mockito默认会在每个测试方法执行后重置mock的Stub状态,所以不用担心不同用例之间的Stub污染。

内容的提问来源于stack exchange,提问作者emoleumassi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 18:14:50