开发者社区> 问答> 正文

模拟restTemplate抛出org.mockito.exceptions.misusing.Un

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

js

```  
org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:
-> at com.unittest.weather.forcast.service.WeatherRemoteServiceTest.testRetrieveWeather(WeatherRemoteServiceTest.java:55)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed

    at com.unittest.weather.forcast.service.WeatherRemoteServiceTest.testRetrieveWeather(WeatherRemoteServiceTest.java:55)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:44)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:74)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:80)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Iterator.forEachRemaining(Iterator.java:116)
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
    at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
    at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

```  


```js
@RunWith(MockitoJUnitRunner.class)
public class WeatherRemoteServiceTest {

    @Mock CustomResttemplate restTemplate;

    @Mock WeatherRemoteUtilies weatherUtilies;

    @InjectMocks WeatherRemoteService weatherRemote;


    @Before
    public void setUp() throws Exception {
    }

    @Test
    public void testRetrieveWeather() {

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

}

```  
这是业务逻辑本身的代码


```js
@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的代码

```js
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工厂上设置setInterceptor

```js
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;
    }
}
```

展开
收起
垚tutu 2019-11-28 19:16:52 1080 0
0 条回答
写回答
取消 提交回答
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载