【问题标题】:How to capture HTTP request and mock its response in Java?如何在 Java 中捕获 HTTP 请求并模拟其响应?
【发布时间】:2020-06-28 09:28:55
【问题描述】:

假设 Java 应用程序向 http://www.google.com/... 发出请求,并且无法配置继承的库(在内部发出此类请求),所以我无法存根或替换此 URL。

请分享一些创建模拟的最佳实践

whenCalling("http://www.google.com/some/path").withMethod("GET").thenExpectResponse("HELLO")

因此,任何 HTTP 客户端对该 URL 的请求都将被重定向到模拟,并在当前 JVM 进程的上下文中替换为该响应 "HELLO"

我尝试使用 WireMock、Mockito 或 Hoverfly 找到解决方案,但他们似乎做了一些不同的事情。可能我只是没有正确使用它们。

您能否展示一下main 方法的简单设置,例如:

  1. 创建模拟
  2. 开始模拟模拟
  3. 由任意 HTTP 客户端(未与模拟库纠缠)向 URL 发出请求
  4. 接收模拟响应
  5. 停止模拟模拟
  6. 发出与第 3 步相同的请求
  7. 从 URL 接收真实响应

【问题讨论】:

  • 如果您无法控制代码,您可能需要在操作系统级别重写调用

标签: java http mocking wiremock http-mock


【解决方案1】:

以下是使用API Simulator 实现您想要的目标的方法。

该示例演示了将 Embedded API Simulator 配置为 Spring 的 RestTemplate 客户端的 HTTP 代理的两种不同方法。检查(引用问题)“继承库”的文档 - 基于 Java 的客户端通常依赖于 here 描述的系统属性,或者可能提供一些使用代码配置 HTTP 代理的方法。

package others;

import static com.apisimulator.embedded.SuchThat.*;
import static com.apisimulator.embedded.http.HttpApiSimulation.*;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URI;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import com.apisimulator.embedded.http.JUnitHttpApiSimulation;

public class EmbeddedSimulatorAsProxyTest
{

   // Configure an API simulation. This starts an instance of
   // Embedded API Simulator on localhost, default port 6090.
   // The instance is automatically stopped when the test ends.
   @ClassRule
   public static final JUnitHttpApiSimulation apiSimulation = JUnitHttpApiSimulation
         .as(httpApiSimulation("my-sim"));

   @BeforeClass
   public static void beforeClass()
   {
      // Configure simlets for the API simulation
      // @formatter:off
      apiSimulation.add(simlet("http-proxy")
         .when(httpRequest("CONNECT"))
         .then(httpResponse(200))
      );

      apiSimulation.add(simlet("test-google")
         .when(httpRequest()
               .whereMethod("GET")
               .whereUriPath(isEqualTo("/some/path"))
               .whereHeader("Host", contains("google.com"))
          )
         .then(httpResponse()
               .withStatus(200)
               .withHeader("Content-Type", "application/text")
               .withBody("HELLO")
          )
      );
      // @formatter:on
   }

   @Test
   public void test_using_system_properties() throws Exception
   {
      try
      {
         // Set these system properties just for this test
         System.setProperty("http.proxyHost", "localhost");
         System.setProperty("http.proxyPort", "6090");

         RestTemplate restTemplate = new RestTemplate();

         URI uri = new URI("http://www.google.com/some/path");
         ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);

         Assert.assertEquals(200, response.getStatusCode().value());
         Assert.assertEquals("HELLO", response.getBody());
      }
      finally
      {
         System.clearProperty("http.proxyHost");
         System.clearProperty("http.proxyPort");
      }
   }

   @Test
   public void test_using_java_net_proxy() throws Exception
   {
      SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

      // A way to configure API Simulator as HTTP proxy if the HTTP client supports it
      Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress("localhost", 6090));
      requestFactory.setProxy(proxy);

      RestTemplate restTemplate = new RestTemplate();
      restTemplate.setRequestFactory(requestFactory);

      URI uri = new URI("http://www.google.com/some/path");
      ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);

      Assert.assertEquals(200, response.getStatusCode().value());
      Assert.assertEquals("HELLO", response.getBody());
   }

   @Test
   public void test_direct_call() throws Exception
   {
      RestTemplate restTemplate = new RestTemplate();

      URI uri = new URI("http://www.google.com");
      ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);

      Assert.assertEquals(200, response.getStatusCode().value());
      Assert.assertTrue(response.getBody().startsWith("<!doctype html>"));
   }

}

使用 maven 时,将以下内容添加到项目的 pom.xml 以包含 Embedded API Simulator 作为依赖项:

    <dependency>
      <groupId>com.apisimulator</groupId>
      <artifactId>apisimulator-http-embedded</artifactId>
      <version>1.6</version>
    </dependency>

... 这指向存储库:

  <repositories>
    <repository>
        <id>apisimulator-github-repo</id>
        <url>https://github.com/apimastery/APISimulator/raw/maven-repository</url>
     </repository>
  </repositories>

【讨论】:

  • 太棒了!这可能比我应该拥有的还要好。您能否将在项目中使用 API Simulator 所需的 maven 依赖项添加到答案中?在那之后,答案将是完整的,我将接受它。
  • 嗨@diziaq - 编辑答案以添加有关如何将嵌入式 API 模拟器作为依赖项添加到 maven 管理的项目的信息。你应该看看真正的主力 - 独立 API 模拟器 :-) 干杯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 2021-07-08
  • 2012-09-15
  • 2015-09-21
相关资源
最近更新 更多