1

在我的应用程序中,我有外部第三方 API 请求。我想通过模拟这个 API 请求来测试我的应用程序。

我的服务等级:

String API_URL = "https://external.com/v1/%s";
private CloseableHttpClient httpClient;
public Result executeRequest(String apiVersion, String subUrl, HttpMethod httpMethod)
{
    try
    {
        HttpRequestBase httpRequest;
        String url = String.format(API_URL, subUrl);
        if (httpMethod.equals(HttpMethod.GET))
        {
            httpRequest = new HttpGet(url);
        }
        else if (httpMethod.equals(HttpMethod.POST))
        {
            httpRequest = new HttpPost(url);
            ((HttpPost) httpRequest).setEntity(new StringEntity(requestBody, "UTF-8"));
        }
        ...
        headers.forEach(httpRequest::setHeader);
        HttpResponse response = httpClient.execute(httpRequest);
    }
    catch (IOException e)
    {
        logger.error("IO Error: {}", e.getMessage());
        return handleExceptions(e);
    }
}

总结服务类,请求可以是get、post、delete、put。并且此请求将使用标头或正文部分进行处理。然后将作为http请求处理。

我的测试课:

@SpringBootTest
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
public class ServiceTest
{

    private static final String API_URL = "https://external.com/v1";

    @Autowired
    private Service service;

    @Autowired
    private RestTemplate restTemplate;

    private MockRestServiceServer mockServer;

     @Before
     public void init()
      {
        mockServer = MockRestServiceServer.createServer(restTemplate);
      }

    @Test
    public void getResult_successfully()
    {
        Result result = new Result();
        mockServer.expect(ExpectedCount.once(),
                requestTo("/subUrl"))
                .andExpect(method(HttpMethod.GET))
                .andRespond(withStatus(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(gson.toJson(result))
                );

        Result returnResult = service.executeRequest("/subUrl", GET);

        mockServer.verify();
        assertThat(returnResult).isEqualTo(result);
    }
}

当我像上面那样实现它时,模拟不起作用。有什么建议吗?

我在这里知道,MockRestServiceServer 仅适用于 restTemplate 请求,但我想知道有没有办法用 httpClient 处理它?

注意:我希望代码片段足以整体理解代码。

4

1 回答 1

0

我为此使用了模拟服务器。您可以对响应进行硬编码(如下例所示)或将请求传递到实际服务器。

private static ClientAndServer mockServer;

@BeforeClass
public static void startServer() {
    mockServer = ClientAndServer.startClientAndServer(1080);
}

@AfterClass
public static void stopServer() { 
    mockServer.stop();
    mockServer = null;
}

@Test
public void getShouldWork() throws URISyntaxException, IOException {
    final String responseBody = "some_response_body";
    final String respHdrName = "some_header";
    final String respHdrVal = "some value";
    
    mockServer.when(
            request()
                .withMethod("GET")
                .withPath("/some/url")
                .withQueryStringParameter("id", "9"),
            Times.exactly(1)
        )
        .respond(
            response()
                .withBody(responseBody)
                .withHeader(respHdrName, respHdrVal)
        );

    
    CloseableHttpClient httpClient = HttpClientBuilder.create()
            .build();
    
    HttpGet getRequest = new HttpGet("http://localhost:" + mockServer.getPort() 
            + "/some/url?id=9");
    CloseableHttpResponse resp = httpClient.execute(getRequest);
    try (InputStreamReader isr = new InputStreamReader(resp.getEntity().getContent());
            BufferedReader br = new BufferedReader(isr);) {
        assertThat(br.readLine(), is(responseBody));
        while (br.readLine() != null) {
            // consume content...
        }
    }
    assertThat(
            resp.getFirstHeader(respHdrName), 
            is(notNullValue()));
    assertThat(
            resp.getFirstHeader(respHdrName).getValue(), 
            is(respHdrVal));
}

上述的相关进口是:

import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.matchers.Times;

最后,必要库的 maven 坐标:

    <dependency>
        <groupId>org.mock-server</groupId>
        <artifactId>mockserver-netty</artifactId>
        <version>5.11.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mock-server</groupId>
        <artifactId>mockserver-client-java</artifactId>
        <version>5.11.2</version>
        <scope>test</scope>
    </dependency>
于 2020-12-29T19:57:30.023 回答