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

使用Mock运行单元测试报错:when()参数需为Mock对象方法调用

解决Mockito报错:when() requires an argument which has to be 'a method call on a mock'

问题根源

你用@Mock注解声明了apiClientUtilsMock作为Mock对象,但在setup()方法里又执行了apiClientUtilsMock = new ApiClientUtils(new ApiClientTimeoutConfiguration());——这行代码直接把Mockito生成的Mock对象覆盖成了真实的ApiClientUtils实例。后续调用when(apiClientUtilsMock.createClientCredentialsResourceDetails(...))时,操作的是真实对象而非Mock对象,因此触发报错。

修复步骤

直接删除setup()方法中创建真实ApiClientUtils实例的代码行:

apiClientUtilsMock = new ApiClientUtils(new ApiClientTimeoutConfiguration());

Mockito会通过@Mock注解自动生成并注入Mock实例,无需手动创建真实对象。

修复后的完整测试类代码

@ExtendWith(MockitoExtension.class)
class CustomerDaoConfigurationTest {

    private CustomerDaoConfiguration customerDaoConfiguration;

    private CustomerApiProperties properties;
    @Mock
    private ApiClientUtils apiClientUtilsMock;
    @Mock // 单元测试无需@MockBean,换成@Mock即可
    private ApiClientTimeoutConfiguration apiClientTimeoutConfiguration;


    @BeforeEach
    void setup() {
        properties = new CustomerApiProperties();
        properties.setBaseUrl("MockBaseUrl");
        properties.setOauth(new OAuthProperties("token-url", "client-id", "client-secret"));

        customerDaoConfiguration = new CustomerDaoConfiguration(properties, apiClientUtilsMock, apiClientTimeoutConfiguration);

    }

    @Test
    void shouldCreateValidRestTemplateWhenPropertiesAreProvided() {

        ClientCredentialsResourceDetails clientCredentialsResourceDetails = new ClientCredentialsResourceDetails();
        clientCredentialsResourceDetails.setClientSecret("client-secret");
        clientCredentialsResourceDetails.setClientId("client-id");
        clientCredentialsResourceDetails.setTokenName("token-name");
        clientCredentialsResourceDetails.setAccessTokenUri("token-url");

        OAuthProperties oauth = properties.getOauth();

        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        messageConverters.add(new JsonApiHttpMessageConverter(new ResourceConverter(), new ObjectMapper()));

        when(apiClientUtilsMock.createClientCredentialsResourceDetails(oauth)).thenReturn(clientCredentialsResourceDetails);

        RestTemplate createdRestTemplate = customerDaoConfiguration.customerRestTemplate(new SimpleClientHttpRequestFactory(), messageConverters);

        assertThat(createdRestTemplate.getMessageConverters().size(), is(1));
        HttpMessageConverter<?> messageConverter = createdRestTemplate.getMessageConverters().get(0);
        assertThat(messageConverter, is(instanceOf(JsonApiHttpMessageConverter.class)));

    }
}

额外说明

  • @MockBean是Spring Boot集成测试专用注解,用于向Spring容器注入Mock对象;纯单元测试场景下,用@Mock配合MockitoExtension即可完成Mock对象的创建。
  • 这是Mockito使用的常见坑点:如果用注解声明了Mock对象,切勿再手动创建真实实例覆盖它,否则Mockito无法拦截方法调用进行Mock配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 03:50:36