当前位置: 首页 > 知识库问答 >
问题:

如何单元测试调用泽西客户端API的代码?

莫繁
2023-03-14

我编写了调用泽西岛客户端API的代码,而该API又调用了我无法控制的Web服务。我不希望我的单元测试调用实际的 Web 服务。

为调用Jersey客户端API的代码编写单元测试的最佳方法是什么?我应该使用Jersey服务器API编写JAX-RS web服务,然后使用Jersy测试框架进行单元测试吗?还是应该模拟Jersey web服务调用?我有权访问JMock。还是我应该尝试另一种方法?

在我的研究中,我发现这个讨论描述了各种选择,但我确实找到了一个完整的解决方案。是否有任何代码示例可以显示建议的JUnit方法?我在泽西岛文档中找不到任何信息。

以下是相关的源代码:

public String getResult(URI uri) throws Exception {
  // error handling code removed for clarity
  ClientConfig clientConfig = new DefaultClientConfig();
  Client client = Client.create(clientConfig);
  WebResource service = client.resource(uri);
  String result = service.accept(accept).get(String.class);
  return result;
}

以下是我想通过的测试代码示例。我想测试(1)传入有效的URI并返回有效的字符串,以及(2)传入无效的(无论出于何种原因——无法访问或未经授权)URI并返回异常。

@Test
public void testGetResult_ValidUri() throws Exception {
  String xml = retriever.getResult(VALID_URI);
  Assert.assertFalse(StringUtils.isBlank(xml));
}

@Test(expected = IllegalArgumentException.class)
public void testGetResult_InvalidUri() throws Exception {
  retriever.getResult(INVALID_URI);
}

上面的一切都是对我的代码所做的简单描述。实际上,在它之上还有一层接受两个URIs,首先尝试调用第一个URI,如果那个URI失败了,它就尝试调用第二个URI。我希望单元测试覆盖(1)第一个URI成功,(2)第一个URI失败,第二个URI成功,以及(3)两个URIs失败。这段代码非常复杂,我想使用JUnit测试这些不同的场景,但是要做到这一点,我要么需要运行实际的代理web服务,要么模拟Jersey客户端API调用

共有3个答案

蒯胜泫
2023-03-14

只需实现一个类似工作的服务,然后在单元测试设置中使用HttpServerFactory启动该服务。

乜承嗣
2023-03-14

通常,您真正想要的是“我使用Jersey客户端DSL的方式是否使用正确的负载和URL参数生成对正确URL的请求?”。使用Mockito进行测试非常冗长,设置代码通常会如下所示:

    when(authentication.queryParam(eq("sa"), anyBoolean())).thenReturn(testAuthentication);
    when(testAuthentication.resolveTemplate("channel", "smf")).thenReturn(testAuthentication);
    when(testAuthentication.request(
            MediaType.APPLICATION_JSON_TYPE)).thenReturn(mockRequestBuilder);
    when(mockRequestBuilder.post(any(Entity.class))).thenReturn(mockResponse);
    when(mockResponse.readEntity(ResponseWrapper.class)).thenReturn(successfulAuthResponse());

这基本上只是针对一个单独的REST请求。它过于冗长,而且您并没有测试所希望的结果,而是在使用Jersey客户端DSL时重复您认为正确的步骤。

与上述内容不同,我的目标是模拟一个简单的服务。为此,我使用了WireMock,它启动了一个Jettyhtml" target="_blank">服务器,我可以在其中存根诸如“期望对此URL的请求,用此消息响应并验证有效负载是这个”之类的东西。

我知道这是在集成测试上的边缘,它比仅仅使用Mockito慢一点,但我重视测试真正的结果,在这种情况下,我更重视测试的可读性。

基于WireMock的Jersey客户端测试的设置如下:

@Test
public void exactUrlOnly() {
    stubFor(get(urlEqualTo("/some/thing"))
            .willReturn(aResponse()
                .withHeader("Content-Type", "text/plain")
                .withBody("Hello world!")));

   assertThat(testClient.get("/some/thing").statusCode(), is(200));
   assertThat(testClient.get("/some/thing/else").statusCode(), is(404));
}
山疏珂
2023-03-14

尝试使用Mockito或Easymock来模拟服务调用。您只需要模拟这些实际使用的方法——不需要模拟每个方法。您可以为WebResource类创建模拟对象,然后模拟accept方法调用。

在@BeforeClass/@Before JUnit测试方法中,写类似的东西(Mockito示例)

WebResource res = mock(WebResource.class);
when(res.accept(something)).thenReturn(thatWhatYouWant);

然后在您的测试中,您可以像使用真实对象一样使用res对象并对其调用mock方法。除了返回值,您还可以抛出异常。Mockito很酷。

 类似资料:
  • 我使用客户机对一个API进行REST调用,该API返回mulipart中的一个Json和一个PDF文件作为响应的第一和第二部分。 使用上面的客户端解析这个多部分响应的正确方法是什么?

  • 我有一个网站,我只是想写一个脚本,发送字符串到一个文本输入在页面(唯一的一个)和点击提交。我构建了一个selenium系统,但被告知这是矫枉过正的,访问页面上的endpoint并以这种方式发送文本要“容易”得多。 线程“main”java.lang.IllegalStateException中出现异常:未找到InjectionManagerFactory。在org.glassfish.jersey

  • 我设计了一个多部分Jersey REST服务,如下所示,用于接收多部分请求(文件上传)并将文件保存在磁盘位置: 我的测试客户是: 但我无法得到回应。 当我使用HTML网页作为客户端通过调用REST服务上传文件时,它工作得很好,但从REST客户端它不工作。 客户有什么需要更改的吗?

  • 我正在请求put操作,在执行请求后,我将重定向到GET服务URL。在这里,我面临着405 HTTP错误代码的问题。然而,在POST操作的情况下,同样的代码也适用于我。 下面的代码是endpoint: 客户: } 请告诉我如何解决这个问题。

  • 问题内容: 我目前正在编写Java客户端服务器应用程序。所以我想实现两个库,一个用于客户端,一个用于服务器。客户端服务器通信具有非常严格的协议,我不打算使用JUnit进行测试。 作为构建工具,我使用Maven和Husdon Server进行持续集成。 实际上,我对如何测试这些客户端/服务器库没有什么好主意。 我得到以下方法: 只需编写一个虚拟客户端来测试服务器,然后编写一个虚拟服务器来测试客户端。

  • 问题内容: 我正在尝试使用Jersey客户端模拟对我的Web服务的HTTP请求。我尝试实现文档中的简单示例。这是我的短代码: 我什至没有实现整个示例,因为当前我在最后一行收到一个异常: 我只将此依赖项添加到我的: 我试图用谷歌搜索问题,以及调试应用程序,但我真的看不出问题出在哪里。 编辑 所有Maven依赖项: 问题答案: 这看起来像与JAX-RS API版本(包含MultiValuedMap)有