【问题标题】:ResourceAccessException: I/O error on POST requestResourceAccessException:POST 请求的 I/O 错误
【发布时间】:2020-09-20 13:52:06
【问题描述】:

我有一个服务方法。该方法是通过 POST 请求访问第三方资源。我正在写一个测试,我在日志中看到一个错误。 服务:

@Override
public void sendDoc(String id) throws IOException {
    byte[] zipData = getZipFromIntegration(mongo.getDocument());

    String response;
    HttpStatus httpStatus;
    try {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("file", new MultipartInputStreamFileResource(new ByteArrayInputStream(zipData),
                String.format("%s_some.zip", id)));

        HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);

        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setConnectTimeout(3000);
        clientHttpRequestFactory.setReadTimeout(3000);
        RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);

        response = restTemplate.postForObject(uploadUrl + system,
                requestEntity, String.class);

    } catch (HttpStatusCodeException e) {
        LOG.error("Some error");
    }
}

我的测试

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = NONE, classes = {SendServiceImpl.class})
@EnableAutoConfiguration
@PropertySource(value = "classpath:application.properties", encoding = "UTF-8")
public class SendServiceImplTest {
    @MockBean
    private RestTemplate restTemplate;
    @Autowired
    private SendServiceImpl service;

    @Test
    public void sendDoc() throws IOException {
        when(restTemplate.postForObject(
                anyString(),
                ArgumentMatchers.<HttpEntity<?>>any(),
                ArgumentMatchers.<Class<String>>any()
        ))
                .thenReturn("ok");

        service.sendDoc("55454545uid");
    }
}

但我看到有对真实服务器的调用。测试成功,但在日志中我看到一个错误:

org.springframework.web.client.ResourceAccessException: I/O 错误 “http://some-url.digital.cloud.ru/v1/doc/reg”的 POST 请求

统一更新: 像这样更改测试:

@RunWith(PowerMockRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = SendServiceImpl.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({SendServiceImpl.class, RestTemplate.class})
@PowerMockIgnore({"javax.xml.*", "org.xml.sax.*", "org.w3c.dom.*"})
public class SendServiceImplTest {
    @MockBean
    private RestTemplate restTemplateMock;

    @Autowired
    private SendServiceImpl service;

    @Test
    public void sendDoc() throws IOException {
    RestTemplate restTemplate = PowerMockito.mock(RestTemplate.class);
    whenNew(RestTemplate.class).withArguments(ClientHttpRequestFactory.class).thenReturn(restTemplate);
    when(restTemplate.postForObject(
                anyString(),
                ArgumentMatchers.<HttpEntity<?>>any(),
                ArgumentMatchers.<Class<String>>any()
        ))
                .thenReturn("ok");

        service.sendDoc("55454545uid");
    }
}

现在该对象被 null 替换。即服务中的restTemplate为null。

【问题讨论】:

  • 我看到RestTemplate嵌入在代码中,是通过new操作符创建的。因此,创建 MockBean 是错误的。如何测试我的方法?如何为restTemplate创建一个模拟?此方法无济于事:RestTemplate restTemplate = Mockito.mock (RestTemplate.class);

标签: java unit-testing junit resttemplate


【解决方案1】:

我的问题的解决方案如下:

@RunWith(PowerMockRunner.class)
@SpringBootTest(webEnvironment = NONE, classes = SendServiceImpl.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest({
        SendServiceImpl.class,
        RestTemplate.class,
        HttpComponentsClientHttpRequestFactory.class
})
@MockBean({FileStorageService.class, DocxToPdfConverterService.class})
@PowerMockIgnore({"javax.xml.*", "org.xml.sax.*", "org.w3c.dom.*"})
public class SendServiceImplTest {
    @Test
    public void sendDoc() throws Exception {
        RestTemplate restTemplate = Mockito.mock(RestTemplate.class);

        whenNew(RestTemplate.class).withAnyArguments().thenReturn(restTemplate);

        PowerMockito.when(restTemplate.postForObject(
                anyString(),
                ArgumentMatchers.<HttpEntity<?>>any(),
                ArgumentMatchers.<Class<String>>any()
        )).thenReturn("ok");
    }
// ......any code.......
}

PowerMock 库和 withAnyArguments () 方法帮助了我。

【讨论】:

    猜你喜欢
    • 2019-01-21
    • 2019-08-29
    • 1970-01-01
    • 2018-07-10
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    相关资源
    最近更新 更多