相关文章推荐
难过的炒饭  ·  protobuf - 简书·  1 年前    · 
另类的开水瓶  ·  Bootstrap ...·  1 年前    · 
阳光的枇杷  ·  人民法院报·  1 年前    · 

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

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; 企业邮箱发送邮件时,若出现投递失败产生退信,内容提示包含如下: the mta server of * reply:550 failed to meet SPF requirements 或者 the mta server of 163.com — 163mx01.mxmail.netease.com(220.181.14.141) reply:550 MI:SPF mx14,QMCowECpA0qTiftVaeB3Cg—.872S2 1442548128 http://mail.163.com/help 299554