Рубрики
Без рубрики

Введение в документы весеннего ОТДЫХА

В этой статье представлены Spring REST Docs, механизм, основанный на тестировании, для создания точной и читаемой документации для служб RESTful.

Автор оригинала: baeldung.

1. Обзор

Spring REST Docs создает документацию для служб RESTful, которая является точной и читаемой. Он сочетает в себе рукописную документацию с автоматически сгенерированными фрагментами документов, полученными с помощью весенних тестов.

2. Преимущества

Одной из основных философий проекта является использование тестов для подготовки документации. Это гарантирует, что всегда создаваемая документация точно соответствует фактическому поведению API. Кроме того, выходные данные готовы к обработке Asciidoctor , цепочкой инструментов публикации, сосредоточенной на синтаксисе AsciiDoc. Это тот же инструмент, который используется для создания документации Spring Framework.

Эти подходы уменьшают ограничения, налагаемые другими рамками. Spring REST Docs создает точную, краткую и хорошо структурированную документацию. Затем эта документация позволяет потребителям веб-сервисов получать необходимую им информацию с минимальными затратами.

Инструмент имеет некоторые другие преимущества, такие как:

  • генерируются фрагменты curl и http-запросов
  • легко упаковывать документацию в файл jar проектов
  • легко добавлять дополнительную информацию к фрагментам
  • поддерживает как JSON, так и XML

Тесты, которые создают фрагменты, могут быть написаны с использованием либо поддержки тестов Spring MVC, либо Spring Webflux Клиент веб-тестирования или БУДЬТЕ Уверены.

В наших примерах мы будем использовать тесты Spring MVC, но использование других фреймворков очень похоже.

3. Зависимости

Идеальный способ начать использовать документы Spring REST в проекте-это использовать систему управления зависимостями. Здесь мы используем Maven в качестве инструмента сборки, поэтому приведенную ниже зависимость можно скопировать и вставить в ваш POM:


    org.springframework.restdocs
    spring-restdocs-mockmvc
    2.0.4.RELEASE

Вы также можете проверить Maven Central на наличие новой версии зависимости здесь .

В нашем примере нам нужна зависимость spring-restdocs-mockmvc , поскольку мы используем поддержку тестов Spring MVC для создания наших тестов.

Если мы хотим писать тесты с помощью клиента WebTest или БУДЬТЕ уверены, нам понадобятся зависимости spring-restdocs-web test client и spring-restdocs-restassured .

4. Конфигурация

Как уже упоминалось, мы будем использовать Spring MVC Test framework для выполнения запросов к службам REST, которые должны быть задокументированы. Запуск теста создает фрагменты документации для запроса и результирующего ответа.

Мы можем использовать библиотеку как с тестами JUnit 4, так и с тестами JUnit 5. Давайте рассмотрим конфигурацию, необходимую для каждого из них.

4.1. Конфигурация JUnit 4

Самым первым шагом в создании фрагментов документации для тестов JUnit 4 является объявление общедоступного JUnitRestDocumentation поля, аннотированного как правило JUnit @ .

Правило JUnit Test Documentation настраивается с помощью выходного каталога, в который должны быть сохранены сгенерированные фрагменты. Например, этот каталог может быть каталогом сборки Maven:

@Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");

Затем мы настроим контекст MockMvc таким образом, чтобы он был настроен для создания документации:

@Autowired
private WebApplicationContext context;

private MockMvc mockMvc;

@Before
public void setUp(){
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
      .apply(documentationConfiguration(this.restDocumentation))
      .build();
}

Объект MockMvc настраивается с помощью MockMvc Rest Documentation Configure . Экземпляр этого класса можно получить из метода static documentation Configuration() на org.springframework.restdocs.mockmvc.MockMvcRestDocumentation .

4.2. Конфигурация JUnit 5

Чтобы работать с тестом Unit 5, мы должны расширить тест с помощью Расширение документации Rest класс:

@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
@SpringBootTest
public class ApiDocumentationJUnit5IntegrationTest { //... }

Этот класс автоматически настраивается с помощью каталога /target/generated-snippets output при использовании Maven или /build/generate-snippets для Gradle.

Затем мы должны настроить экземпляр MockMvc в методе @beforeEach :

@BeforeEach
public void setUp(WebApplicationContext webApplicationContext,
  RestDocumentationContextProvider restDocumentation) {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
      .apply(documentationConfiguration(restDocumentation)).build();
}

Если мы не используем JUnit для тестов, то мы должны использовать Документация по ручному Отдыху класс.

5. Спокойное обслуживание

Давайте создадим сервис CRUD RESTful, который мы сможем документировать:

@RestController
@RequestMapping("/crud")
public class CRUDController {
	
    @GetMapping
    public List read(@RequestBody CrudInput crudInput) {
        List returnList = new ArrayList();
        returnList.add(crudInput);
        return returnList;
    }
	
    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping
    public HttpHeaders save(@RequestBody CrudInput crudInput) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setLocation(
          linkTo(CRUDController.class).slash(crudInput.getTitle()).toUri());
        return httpHeaders;
    }
	
    @DeleteMapping("/{id}")
    public void delete(@PathVariable("id") long id) {
        // delete
    }
}

Затем давайте также добавим IndexController , который возвращает страницу со ссылкой на CRUD-контроллер базовую конечную точку:

@RestController
@RequestMapping("/")
public class IndexController {

    static class CustomRepresentationModel extends RepresentationModel {
        public CustomRepresentationModel(Link initialLink) {
            super(initialLink);
        }
    }

    @GetMapping
    public CustomRepresentationModel index() {
        return new CustomRepresentationModel(linkTo(CRUDController.class).withRel("crud"));
    }
}

6. Тесты JUnit

Вернувшись в тесты, мы можем использовать экземпляр MockMvc для вызова наших служб и документирования запроса и ответа.

Во-первых, чтобы убедиться, что каждый вызов MockMvc автоматически документируется без какой-либо дополнительной настройки, мы можем использовать метод alwaysDo () :

this.mockMvc = MockMvcBuilders
  //...
  .alwaysDo(document("{method-name}", 
    preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
  .build();

Эта настройка гарантирует, что для каждого вызова MockMvc фрагменты по умолчанию создаются в папке с именем метода тестирования. Кроме того, применение препроцессора pretty Print() отображает фрагменты в более удобочитаемом виде.

Давайте продолжим настройку некоторых наших вызовов.

Для документирования нашей индексной страницы, содержащей ссылку, мы можем использовать статическую связи() метод:

@Test
public void indexExample() throws Exception {
    this.mockMvc.perform(get("/")).andExpect(status().isOk())
      .andDo(document("index", 
        links(linkWithRel("crud").description("The CRUD resource")), 
        responseFields(subsectionWithPath("_links")
          .description("Links to other resources"))
        responseHeaders(headerWithName("Content-Type")
          .description("The Content-Type of the payload"))));
}

Здесь мы используем метод link With Rel() для документирования ссылки на /crud.

Чтобы добавить заголовок Content-Type в ответ, мы документируем его с помощью метода header With Name() и добавляем его в метод responseHeaders () .

Мы также документируем полезную нагрузку ответа, используя метод response Fields () . Это может быть использовано для документирования более сложного подраздела ответа или отдельного поля с использованием методов подраздела с Path() или fieldWithPath ().

Аналогично полезной нагрузке ответа, мы также можем документировать полезную нагрузку запроса, используя полезную нагрузку запроса():

@Test
public void crudCreateExample() throws Exception {
    Map crud = new HashMap<>();
    crud.put("title", "Sample Model");
    crud.put("body", "http://www.baeldung.com/");
       
    this.mockMvc.perform(post("/crud").contentType(MediaTypes.HAL_JSON)
      .content(this.objectMapper.writeValueAsString(crud)))
      .andExpect(status().isCreated())
      .andDo(document("create-crud-example", 
        requestFields(fieldWithPath("id").description("The id of the input"),
          fieldWithPath("title").description("The title of the input"),
          fieldWithPath("body").description("The body of the input"),
        ))));
}

В этом примере мы задокументировали наш запрос POST, который получает Сырой ввод модель с полями заголовка и тела и отправляет статус СОЗДАНИЯ. Каждое поле документируется с помощью метода field With Path () .

Для документирования запроса и параметра пути мы можем использовать методы Параметры запроса() и Параметры пути () . Оба метода используют параметр С именем() метод для описания каждого параметра:

@Test
public void crudDeleteExample() throws Exception {
    this.mockMvc.perform(delete("/crud/{id}", 10)).andExpect(status().isOk())
      .andDo(document("crud-delete-example", 
      pathParameters(
        parameterWithName("id").description("The id of the input to delete")
      )));
}

Здесь мы задокументировали нашу конечную точку удаления, которая получает параметр id path.

Проект Spring REST Docs содержит еще более мощные функции документации, такие как ограничения полей и части запросов, которые можно найти в documentation .

7. Выход

После успешного выполнения сборки выходные данные остальных фрагментов документов будут сгенерированы и сохранены в папке target/generated-snippets :

Снимок экрана 2016-04-04 в 11.48.52 вечера

Сгенерированные выходные данные будут содержать информацию о службе, о том, как вызывать службу REST, например вызовы “curl”, HTTP-запрос и ответ от службы REST, а также ссылки/конечные точки на службу:

Команда CURL

----
$ curl 'http://localhost:8080/' -i
----

Ответ HTTP – REST

[source,http,options="nowrap"]
----
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Length: 93

{
  "_links" : {
    "crud" : {
      "href" : "http://localhost:8080/crud"
    }
  }
}
----

8. Использование фрагментов для создания документации

Чтобы использовать фрагменты в более крупном документе, вы можете ссылаться на них с помощью Asciidoc includes. В нашем случае мы создали документ в src/docs под названием api-guide.adoc :

Снимок экрана 2016-05-01 в 8.51.48 вечера

В этом документе, если мы хотим ссылаться на фрагмент ссылки, мы можем включить его, используя заполнитель {фрагменты} , который будет заменен Maven при обработке документа:

==== Links

include::{snippets}/index-example/links.adoc[]

9. Плагины Ascii docs Maven

Чтобы преобразовать руководство API из Asciidoc в читаемый формат, мы можем добавить плагин Maven в жизненный цикл сборки. Есть несколько шагов, чтобы включить это:

  1. Примените плагин Asciidoctor к pom.xml
  2. Добавьте зависимость от spring-restdocs-mockmvc в конфигурацию testCompile , как указано в разделе зависимости
  3. Настройте свойство для определения местоположения вывода для сгенерированных фрагментов
  4. Настройте задачу test для добавления каталога фрагментов в качестве выходных данных
  5. Настройте задачу asciidoctor
  6. Определите атрибут с именем snippets , который можно использовать при включении сгенерированных фрагментов в документацию
  7. Поставьте задачу в зависимость от задачи test , чтобы тесты выполнялись до создания документации
  8. Настройте каталог сниппеты в качестве входных данных. Все сгенерированные фрагменты будут созданы в этом каталоге

Добавьте каталог фрагментов в качестве свойства в pom.xml таким образом, плагин Asciidoctor может использовать этот путь для создания фрагментов в этой папке:


    ${project.build.directory}/generated-snippets

Конфигурация плагина Maven в pom.xml чтобы сгенерировать фрагменты Asciidoc из сборки, выполните следующие действия:

 
    org.asciidoctor
    asciidoctor-maven-plugin
    1.5.6
    
        
            generate-docs
            package 
            
                process-asciidoc
            
            
                html
                book
                
                    ${snippetsDirectory} 
                
                src/docs/asciidocs
                target/generated-docs
             
	 
    

10. Процесс Генерации документов API

Когда сборка Maven будет запущена и тесты будут выполнены, все фрагменты будут сгенерированы в папке фрагменты в каталоге настроенные целевые/сгенерированные-фрагменты . После создания фрагментов процесс сборки генерирует выходные данные HTML.

Снимок экрана 2016-05-08 в 11.32.25 вечера

Сгенерированный HTML – файл отформатирован и читаем, поэтому ОСТАЛЬНАЯ документация готова к использованию. Каждый раз, когда выполняется сборка Maven, документы также генерируются с последними обновлениями.

11. Заключение

Отсутствие документации лучше, чем неправильная документация, но документы Spring REST помогут создать точную документацию для служб RESTful.

Как официальный проект Spring, он достигает своих целей с помощью трех тестовых библиотек: Spring MVC Test, Web Test Client и БУДЬТЕ уверены. Этот метод создания документации может помочь поддержать основанный на тестировании подход к разработке и документированию API RESTful.

Вы можете найти пример проекта, основанного на коде в этой статье, в связанном репозитории GitHub .