Всем привет. Этот цикл статей будет полезен тем, кто хочет изучить процесс создания и тестирования REST API. Автоматизаторам это будет особенно полезно в том случае, если к REST-клиенту нет доступа или сервер не достаточно стабильный, но для дальнейшей разработки необходимо его тестирование. В таких случая довольно сложно провести автоматизированное тестирование. Выходом является создание заглушки, которая будет эмулировать работу сервера при обработке REST. Об этом и пойдет речь.
Dropwizard
Dropwizard – это Java-фреймворк, который позволяет строить RESTful веб-сервисы. Он имеет хорошую документацию как создать проект с нуля. Использую его для создания своего. Шаги описаны ниже:
- Создать Maven проект
- Добавить зависимость Dropwizard
- Собрать проект Maven
- Добавить файл конфигурации
- Добавить класс конфигурации
- Добавить класс данных
- Добавить классы сервисов
- Проверить работоспособность
- Добавить приложение Dropwizard
- Собрать все в JAR файл
- Запустить собарнный файл
- Протестировать работоспособность сервисов
Создание проекта Maven
Убедитесь, что Maven установлен. Перейдите в директорию, в которой вы хотите создать проект. Выполните команду, где “groupId” – название Java пакета и “artifactId” – название проекта:
1 2 3 4 |
mvn -B archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.automationrhapsody.reststub -DartifactId=sample-dropwizard-rest-stub |
Также преокт может быть создан со среды разработки (IntelliJ, Eclipse).
Добавление зависимости Dropwizard
Откройте файл pom.xml. Если проект создан с помощью команды Maven, то там должна находится секция <dependencies> с junit. Вы можете удалить ее и добавить вмето нее следующие строки.
1 2 3 4 5 |
<dependency> <groupId>io.dropwizard</groupId> <artifactId>dropwizard-core</artifactId> <version>0.8.0</version> </dependency> |
Сборка проекта Maven
Перейдите в директорию проекта и выполните команду “mvn package”. Первый раз для сборки проекта неоходимо какое-то время, так как нужно подтянуть зависимости в репозиторий Maven. Как только сборка проекта закончится перейдите в выбранную вами IDE и перегрузите Maven JAR-файлы (для IntelliJ в контекстном меню проекта выберите Maven -> Reimport).
Добавление файла конфигурации
Настройки Dropwizard управляются с помощью YAML, которые содержат ключ-значение разделенные двоеточием. Добавьте файл “config.yml” к проекту. Добавьте в него следующую конфигурацию, настроенную на выбранные вами порты:
1 2 3 4 5 6 7 8 9 10 |
version: 0.0.1 # Change default server ports server: applicationConnectors: - type: http port: 9000 adminConnectors: - type: http port: 9001 |
Добавление класса конфигурации
После того как мы добавили файл конфигурации нам нужен класс, который будет обрабатывать его. Для этого он должен наследоваться от класса Configuration и определять поля чтения и записи версии.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.automationrhapsody.reststub; import com.fasterxml.jackson.annotation.JsonProperty; import io.dropwizard.Configuration; import org.hibernate.validator.constraints.NotEmpty; public class RestStubConfig extends Configuration { @NotEmpty private String version; @JsonProperty public String getVersion() { return version; } @JsonProperty public void setVersion(String version) { this.version = version; } } |
Создание класса данных
В нашем примере мы имеем класс Person, который имеет базовые атрибуты. Он имеет только методы возврата значений, которые имеют аннотацию @JsonProperty и позволяет Jackson сериализовать или десериализовать данные с JSON (для этих целей используется пустой конструктор).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.automationrhapsody.reststub.data; import com.fasterxml.jackson.annotation.JsonProperty; public class Person { private int id; private String firstName; private String lastName; private String email; public Person() { // Needed by Jackson deserialization } public Person(int id, String firstName, String lastName, String email) { this.id = id; this.firstName = firstName; this.lastName = lastName; this.email = email; } @JsonProperty public int getId() { return id; } @JsonProperty public String getFirstName() { return firstName; } @JsonProperty public String getLastName() { return lastName; } @JsonProperty public String getEmail() { return email; } } |
Создание сервиса
Аннотация @Path определяет корневой урл для нашего сервиса. В нашем примере – это “/person” для всего класса и другие подпути для определенных операций. @GET и @POST определяют типы запросов. @Timed используется для аналитических целей. @Produces и @Consumes определяют типы данных.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
package com.automationrhapsody.reststub.resources; import com.automationrhapsody.reststub.data.Person; import com.automationrhapsody.reststub.persistence.PersonDB; import com.codahale.metrics.annotation.Timed; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import java.util.List; @Path("/person") public class PersonService { public PersonService() { } @GET @Timed @Path("/get/{id}") @Produces(MediaType.APPLICATION_JSON) public Person getPerson(@PathParam("id") int id) { return PersonDB.getById(id); } @GET @Timed @Path("/remove") @Produces(MediaType.TEXT_PLAIN) public String removePerson() { PersonDB.remove(); return "Last person remove. Total count: " + PersonDB.getCount(); } @GET @Timed @Path("/all") @Produces(MediaType.APPLICATION_JSON) public List<Person> getPersons() { return PersonDB.getAll(); } @POST @Timed @Path("/save") @Produces(MediaType.TEXT_PLAIN) @Consumes({MediaType.APPLICATION_JSON}) public String addPerson(Person person) { return PersonDB.save(person); } } |
Операции сервиса
Представленный класс отображает создание RESTful-сервиса при работе с данными пользователя. Работу 4 операций можно проверить по следующим ссылкам:
- /person/get/{id} – при передаче “id” человека возвращает JSON с информацией о нем
- /person/remove – удаляет одного с людей
- /person/all – возвращает JSON с информацией о всех людях
- /person/save – принимает JSON с информацией о человеке и сохраняет данные, если “id” уникален, если нет, то обновляет данные человека с существующим id.
В следующей статье мы добавим тестовые данные для манипуляции с сервисами и соберем JAR файл для запуска сервсиса.