1. Обзор
MockServer — это инструмент для имитации/заглушки внешних API-интерфейсов HTTP.
2. Зависимости Maven
Чтобы использовать MockServer
в нашем приложении, нам нужно добавить две зависимости:
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>3.10.8</version>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-client-java</artifactId>
<version>3.10.8</version>
</dependency>
Последняя версия зависимостей доступна как mockserver-netty и mockserver-client.
3. Функциональность мок-сервера
Проще говоря, инструмент может:
- генерировать и возвращать фиксированные ответы
- перенаправить запрос на другой сервер
- выполнять обратные вызовы
- проверить запрос
4. Как запустить MockServer
Мы можем запустить сервер несколькими способами — давайте рассмотрим некоторые из этих способов.
4.1. Запуск через плагин Maven
Это запустит сервер на этапе process-test-class
и остановится на этапе проверки
:
<plugin>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-maven-plugin</artifactId>
<version>3.10.8</version>
<configuration>
<serverPort>1080</serverPort>
<proxyPort>1090</proxyPort>
<logLevel>DEBUG</logLevel>
<initializationClass>org.mockserver.maven.ExampleInitializationClass</initializationClass>
</configuration>
<executions>
<execution>
<id>process-test-classes</id>
<phase>process-test-classes</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<phase>verify</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
4.2. Запуск через Java API
Мы можем использовать Java API startClientAndServer()
для запуска сервера. Обычно мы запускаем сервер перед запуском всех тестов:
public class TestMockServer {
private ClientAndServer mockServer;
@BeforeClass
public void startServer() {
mockServer = startClientAndServer(1080);
}
@AfterClass
public void stopServer() {
mockServer.stop();
}
// ...
}
5. Имитация клиентов
MockServerClient
API используется для предоставления возможности подключения к MockServer.
Он моделирует запросы и соответствующие ответы от сервера.
Он поддерживает несколько операций:
5.1. Создание ожиданий с помощью фиктивных ответов
Ожидания — это механизм, с помощью которого мы имитируем запрос от клиента и результирующий ответ от MockServer.
Чтобы создать ожидание, нам нужно определить сопоставитель запросов и ответ, который должен быть возвращен.
Запросы могут быть сопоставлены с использованием:
- путь — URL-адрес
- строка запроса — параметры URL
- заголовки — заголовки запроса
- куки - куки на стороне клиента
- body — тело запроса POST с XPATH, JSON, схемой JSON, регулярным выражением, точным соответствием параметрам обычного текста или тела
Все вышеперечисленные параметры можно указать с помощью обычного текста или регулярных выражений.
А ответное действие будет содержать:
- коды состояния — действительные коды состояния HTTP, например, 200, 400 и т. д.
- тело — это последовательность байтов, содержащая любой контент
- заголовки — заголовки ответа с именем и одним или несколькими значениями
- куки – ответные куки с именем и одним или несколькими значениями
Давайте посмотрим, как мы можем создать ожидание :
public class TestMockServer {
private void createExpectationForInvalidAuth() {
new MockServerClient("127.0.0.1", 1080)
.when(
request()
.withMethod("POST")
.withPath("/validate")
.withHeader("\"Content-type\", \"application/json\"")
.withBody(exact("{username: 'foo', password: 'bar'}")),
exactly(1))
.respond(
response()
.withStatusCode(401)
.withHeaders(
new Header("Content-Type", "application/json; charset=utf-8"),
new Header("Cache-Control", "public, max-age=86400"))
.withBody("{ message: 'incorrect username and password combination' }")
.withDelay(TimeUnit.SECONDS,1)
);
}
// ...
}
Здесь мы заглушаем POST
-запрос к серверу. И мы указали, сколько раз нам нужно сделать этот запрос, используя вызов точно (1) .
Получив этот запрос, мы имитировали ответ с такими полями, как код состояния, заголовки и тело ответа.
5.2. Пересылка запроса
Ожидание может быть настроено для пересылки запроса. Несколько параметров могут описать прямое действие:
- хост — хост для пересылки, например, www.foreach.com
- порт — порт, на который перенаправляется запрос, порт по умолчанию — 80.
- схема — протокол для использования, например, HTTP или HTTPS
Давайте посмотрим на пример запроса на переадресацию:
private void createExpectationForForward(){
new MockServerClient("127.0.0.1", 1080)
.when(
request()
.withMethod("GET")
.withPath("/index.html"),
exactly(1))
.forward(
forward()
.withHost("www.mock-server.com")
.withPort(80)
.withScheme(HttpForward.Scheme.HTTP)
);
}
В этом случае мы смоделировали запрос, который попадет на MockServer ровно один раз, а затем будет перенаправлен на другой сервер. Внешний метод forward()
определяет действие пересылки, а внутренний вызов метода forward()
помогает создать URL-адрес и перенаправить запрос.
5.3. Выполнение обратного вызова
Сервер может быть настроен на выполнение обратного вызова при получении определенного запроса. Действие обратного вызова может определять класс обратного вызова, реализующий интерфейс org.mockserver.mock.action.ExpectationCallback
. Он должен иметь конструктор по умолчанию и должен находиться в пути к классам.
Давайте посмотрим на пример ожидания с обратным вызовом:
private void createExpectationForCallBack() {
mockServer
.when(
request().withPath("/callback"))
.callback(
callback()
.withCallbackClass("com.foreach.mock.server.TestExpectationCallback")
);
}
Здесь внешний callback()
указывает действие обратного вызова, а внутренний метод callback()
указывает экземпляр класса метода обратного вызова.
В этом случае, когда MockServer получает запрос с /callback,
будет выполнен метод дескриптора обратного вызова, реализованный в указанном классе:
public class TestExpectationCallback implements ExpectationCallback {
public HttpResponse handle(HttpRequest httpRequest) {
if (httpRequest.getPath().getValue().endsWith("/callback")) {
return httpResponse;
} else {
return notFoundResponse();
}
}
public static HttpResponse httpResponse = response()
.withStatusCode(200);
}
5.4. Проверка запросов
MockServerClient
имеет возможность проверить, отправила ли тестируемая система запрос:
private void verifyPostRequest() {
new MockServerClient("localhost", 1080).verify(
request()
.withMethod("POST")
.withPath("/validate")
.withBody(exact("{username: 'foo', password: 'bar'}")),
VerificationTimes.exactly(1)
);
}
Здесь класс org.mockserver.verify.VerificationTimes
используется для указания количества раз, когда фиктивный сервер должен соответствовать запросу.
6. Заключение
В этой быстрой статье мы рассмотрели различные функции MockServer. Мы также изучили различные предоставляемые API и то, как их можно использовать для тестирования сложных систем.
Как всегда, полный код для этой статьи доступен на GitHub.