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
相关产品推荐
相关产品推荐

