Mockito org.mockito.exceptions.misusing.InvalidUseOfMatchersException:参数匹配器的使用无效!预期 0 个匹配器,记录 1 个:

Posted

技术标签:

【中文标题】Mockito org.mockito.exceptions.misusing.InvalidUseOfMatchersException:参数匹配器的使用无效!预期 0 个匹配器,记录 1 个:【英文标题】:Mockito org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 0 matchers expected, 1 recorded: 【发布时间】:2020-03-23 11:19:16 【问题描述】:

首先,我尝试为远程服务编写单元测试以获取天气并使用 restTemplate 然后实现ClientHttpRequestInterceptor 以获取远程请求和远程响应以用于日志记录目的现在我尝试模拟 restTemplate 以编写单元测试并获取以下错误

When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.

and here you here code i wrote for unit-test
@RunWith(MockitoJUnitRunner.class)
public class WeatherRemoteServiceTest 

    @Mock CustomResttemplate restTemplate;

    @Mock WeatherRemoteUtilies weatherUtilies;

    @InjectMocks WeatherRemoteService weatherRemote;

    @Test
    public void testRetrieveWeather() 

        ResponseEntity<String> MockResponse= new ResponseEntity<String>(HttpStatus.OK);

        Mockito.when(weatherUtilies.buildRequestParams(Mockito.anyString()))
                        .thenReturn(Mockito.any(MultiValueMap.class));
        ResponseEntity<String> responseEntity = new ResponseEntity<String>("sampleBodyString", HttpStatus.OK);
        Mockito.when(restTemplate.buildRestTemplate().exchange(
                                   Matchers.anyString(), 
                                   Matchers.any(HttpMethod.class),
                                   Matchers.<HttpEntity<?>> any(), 
                                   Matchers.<Class<String>> any()
                                  )
                                 ).thenReturn(responseEntity);
        assertEquals(weatherRemote.retrieveWeather("ciaro").getStatusCode(), HttpStatus.OK);
    


这是业务逻辑本身的代码

@Service
public class WeatherRemoteService 

    private final Logger logger= LoggerFactory.getLogger(this.getClass());

    @Value("$openweather.url")
    private String url;

    @Autowired
    private WeatherRemoteUtilies weatherUtilies;

    @Autowired
    private CustomResttemplate customRestTemplate;

    public ResponseEntity<?> retrieveWeather(String city) 

        logger.info(Constants.CLASS_NAME+this.getClass().getName()+Constants.METHOD_NAME+new Object() .getClass().getEnclosingMethod().getName());
        logger.debug(Constants.METHOD_ARGUMENTS+city);
        RestTemplate restRequest= customRestTemplate.buildRestTemplate();
        HttpHeaders headers= new HttpHeaders();
        headers.set("Accept",MediaType.APPLICATION_JSON_UTF8_VALUE);
        UriComponentsBuilder uri= UriComponentsBuilder.fromUriString(url).
                path("/data/2.5/weather")
                .queryParams(weatherUtilies.buildRequestParams(city));
        HttpEntity<String>entity= new HttpEntity<>(headers);
        ResponseEntity<String>WeatherResponse=restRequest.exchange(uri.toUriString(), HttpMethod.GET, entity, String.class);
        logger.info(Constants.END_METHOD);
        return WeatherResponse;
    





RestTemplateInterceptor的代码

public class RestTemplateInterceptor implements ClientHttpRequestInterceptor 

    private final Logger logger =LoggerFactory.getLogger(this.getClass());

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException 
        logRequest(request, body);
        ClientHttpResponse httpResponse= execution.execute(request, body);
        logResponse(httpResponse);
        return httpResponse;
    

    private void logRequest(HttpRequest request, byte[] body) throws IOException 
        logger.info(Constants.START_REMOTE_REQUEST);
        logger.info("URI            :", request.getURI().toString());
        logger.info("Method         :", request.getMethod().toString());
        logger.info("Headers        :", request.getHeaders().toString());
        logger.info("Request body   :", new String(body,"UTF-8").toString());
        logger.info(Constants.END_REMOTE_REQUEST);
    

    private void logResponse(ClientHttpResponse response) throws IOException 
        logger.info(Constants.START_REMOTE_RESPONSE);
        logger.info("Status code    :", response.getStatusCode().toString());
        logger.info("Status text    :", response.getStatusText().toString());
        logger.info("Headers        :", response.getHeaders().toString());
        logger.info("Response body  :", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
        logger.info(Constants.END_REMOTE_RESPONSE);
    


然后使用以下代码在 RestTemplate 工厂上设置拦截器


public class CustomResttemplate 

    public RestTemplate buildRestTemplate() 
        SimpleClientHttpRequestFactory simpleFactory= new SimpleClientHttpRequestFactory();
        simpleFactory.setOutputStreaming(false);
        ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(simpleFactory);

        RestTemplate restTemplate= new RestTemplate(factory);
        restTemplate.setInterceptors(Collections.singletonList(new RestTemplateInterceptor()));

        return restTemplate;
    

【问题讨论】:

我已回滚您的编辑。在人们开始回答后,您不应该更改问题,因为这会使他们的回答无效。如果您有新问题,请提出新问题。 好的对不起我再问一个谢谢 【参考方案1】:

你的问题是你写的地方

.thenReturn(Mockito.any(MultiValueMap.class))

您实际上必须告诉 Mockito 要返回什么。你不能在这里使用匹配器。匹配器用于验证和设置要存根的条件。您不能使用它们来告诉 Mockito 从存根调用返回什么。

创建一个特定的MultiValueMap 以传递给thenReturn

【讨论】:

感谢我的空指针异常 ``` java.lang.NullPointerException at com.unittest.weather.forcast.service.WeatherRemoteServiceTest.testRetrieveWeather(WeatherRemoteServiceTest.java:54) ```

以上是关于Mockito org.mockito.exceptions.misusing.InvalidUseOfMatchersException:参数匹配器的使用无效!预期 0 个匹配器,记录 1 个:的主要内容,如果未能解决你的问题,请参考以下文章

Junit mockito

单元测试(mock) 错误org.mockito.Mockito.framework()Lorg/mockito/MockitoFramework;解析

单元测试(mock) 错误org.mockito.Mockito.framework()Lorg/mockito/MockitoFramework;解析

mockito简单教程

Mockito和PowerMock用法

android单元测试框架Mockito使用