Как захватить HTTP-запрос и имитировать его ответ на Java?

Скажем, приложение Java отправляет запросы к http://www.google.com/... и нет возможности настроить унаследованную библиотеку (выполняя такие запросы внутри), поэтому я не могу заглушить или заменить этот URL.

Пожалуйста, поделитесь некоторыми лучшими практиками по созданию макета типа

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

поэтому запрос, сделанный любым HTTP-клиентом на этот URL-адрес, будет перенаправлен на макет и заменен этим ответом "HELLO" в контексте текущего процесса JVM.

Я пытался найти решение с помощью WireMock, Mockito или Hoverfly, но похоже, что они делают что-то другое. Наверное, я просто неправильно их использовал.

Не могли бы вы показать простую настройку из метода main, например:

  1. создать макет
  2. начать имитацию симуляции
  3. сделать запрос к URL-адресу произвольным HTTP-клиентом (не запутанным с насмешливой библиотекой)
  4. получить поддельный ответ
  5. прекратить имитацию симуляции
  6. сделайте тот же запрос, что и на шаге 3
  7. получить реальный ответ от URL

person diziaq    schedule 17.03.2020    source источник
comment
Если у вас нет контроля над кодом, вам может потребоваться переписать вызов на уровне вашей операционной системы.   -  person Smutje    schedule 17.03.2020


Ответы (1)


Вот как добиться желаемого с помощью имитатора API.

В этом примере демонстрируются два разных способа настройки Embedded API Simulator в качестве HTTP-прокси для клиента Spring RestTemplate. Ознакомьтесь с документацией (цитата из вопроса) "унаследованной библиотеки" - часто клиенты на основе Java полагаются на системные свойства, описанные здесь или может предложить способ настройки прокси 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>
person apisim    schedule 18.03.2020
comment
Большой! Это, наверное, даже лучше, чем я предполагал. Не могли бы вы добавить к ответу зависимость maven, которая требуется для использования API Simulator в проекте? После этого ответ будет полным, и я приму его. - person diziaq; 19.03.2020
comment
Привет, @diziaq - отредактировал ответ, чтобы добавить информацию о том, как добавить встроенный API-симулятор в качестве зависимости к проекту, управляемому maven. Вы должны проверить настоящую рабочую лошадку - автономный симулятор API :-) Ура - person apisim; 20.03.2020