Java 莫基托“;然后抛出;不';t在需要时抛出异常

Java 莫基托“;然后抛出;不';t在需要时抛出异常,java,unit-testing,mockito,powermock,Java,Unit Testing,Mockito,Powermock,我在尝试测试表示Rest客户机的类时遇到了一个问题。我在SpringBoot中使用RestTemplate 这是抽象的RestClient类: public abstract class RestClient { ... public RestResponse sendPostRequest(URI baseUri, String resource, IRestRequest restRequest, ClassresponseClass) th

我在尝试测试表示Rest客户机的类时遇到了一个问题。我在SpringBoot中使用RestTemplate

这是抽象的RestClient类:

    public abstract class RestClient {
    ...

    public RestResponse sendPostRequest(URI baseUri, String resource, IRestRequest restRequest, ClassresponseClass)
            throws ServerException, ClientException {

        ...

        try {

            RestTemplate restTemplate = new RestTemplate();
            response = restTemplate.exchange(baseUri, HttpMethod.POST, getEntity(restRequest), responseClass);
            result = response.getBody();

            getLogger().debug("[{}] received", result);
            return result;
        } catch (HttpClientErrorException e) {
            throw new ClientException(e.getCause());
        } catch (HttpServerErrorException e) {
            throw new ServerException(e.getCause());
        } catch (Exception e) {
            getLogger().error("Error with cause: {}.", e.getMessage());
        }

        ...
    }
}
这是实际执行情况:

    public class ActualRestClient extends RestClient {

    public RestResponse sendFetchFileRequest(URI baseUri, FetchFileRequest request) throws ServerException, ClientException {
        return sendPostRequest(baseUri, "FETCH_FILE", request, RestResponse.class);
    }
 }
这是一个测试:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ActualRestClient.class, RestClient.class})
public class ActualResRestClientTest {

private static final String REQUEST_URI = "something";

@InjectMocks
public ActualRestClient testee;

@Mock
private RestTemplate restTemplate;


@Test(expected = ServerException.class)
public void sendPostRequestWithResponseBody_throwsServerException() throws Exception {

    HttpServerErrorException httpServerErrorException = new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR);
    when(restTemplate.exchange(Mockito.any(URI.class), eq(HttpMethod.POST), Mockito.any(), eq(FetchFileRequest.class))).thenThrow(httpServerErrorException);

    testee.sendFetchFileRequest(new URI(REQUEST_URI), new FetchFileRequest());
 }
}
ClientException和ServerException是我通过扩展Exception类创建的异常。
我的问题是在RestClient类中捕获了另一个异常(消息:“URI不是绝对的”)而不是HttpServerErrorException,我不明白为什么。谢谢大家!

正如评论者已经表达的那样:做
新的URI(“某物”)
已经向你抛出了问题。但是,即使您传递了一个“有效”的URI,您的代码也不会工作,因为在您这方面存在误解。你看,

RestTemplate restTemplate = new RestTemplate();
response = restTemplate.exchange(baseUri, HttpMethod.POST, getEntity(restRequest), responseClass);
该代码存在于测试类的方法中。但是@InjectMocks仅适用于类的字段

换句话说:当您的生产代码被执行时,将创建一个新的(完全不同的**ResponseTemplate实例)。因此,您的模拟规范是不相关的,因为该方法首先不会在您的模拟上调用

两种选择:

  • 将该局部变量转换为测试类的字段(然后注入应该可以工作)
  • 或者,由于您已经在使用PowerMock(ito),您可以使用该模拟框架拦截对
    new()
    的调用

我建议您使用选项一,并避免使用PowerMock(ito)扩展!您需要将有效的
URI
传递给
sendFetchFileRequest
方法。因为
URI
的构造函数将验证字符串input@Lino很好,我在写我的答案时忽略了这一点。但现在考虑到了这一点。我已经试过了,谢谢你,@Lino,但重点是我想让它变得更好rk,不管url是什么。捕获
异常通常是个坏主意,除非您真的调用了
抛出异常的方法,并且您无法传播它。捕获您能捕获的最具体的异常。还有另一个问题。RestTemplate有许多“交换”metods,有不同的签名…Mockito没有选择正确的方法。我今天就剪,或者干脆试试!祝你周末愉快亲爱的:)如果你要使用PowerMock,你需要调用PowerMock的expectNew方法来返回你的mockRestTemplate。更好的解决方案是按照@GhostCat的建议进行重构,然后慢慢地离开PowerMock。@MichaelPeacock慢慢地?