由于来自 spring-data-rest 的 HAL“_links”元素,restdocs SnippetException

restdocs SnippetException due to HAL "_links" elements from spring-data-rest

我的应用正在使用 spring-data-restspring-restdocs。 我的设置非常标准;几乎完全从文档中复制,但我在下面包含了示例以防遗漏某些内容。 当我的 mvc 测试运行时,它失败了:

org.springframework.restdocs.snippet.SnippetException: The following parts of the payload were not documented:
{
  "_links" : {
    "self" : {
      "href" : "https://my-api/item/10"
    },
    "item" : {
      "href" : "https://my-api/item/10"
    }
  }
}

这是我的测试代码:

@Rule
public JUnitRestDocumentation restDocs = new JUnitRestDocumentation("target/generated-snippets");
// ...
mockMvc = webAppContextSetup(wac) //WebApplicationContext
        .apply(documentationConfiguration(restDocs)
                       .uris()
                       .withHost("my-api")
                       .withPort(443)
                       .withScheme("https"))
        .build();
// ....
mockMvc.perform(get("/items/{id}", "10"))
               .andDo(documentation)

这是堆栈:

at org.springframework.restdocs.payload.AbstractFieldsSnippet.validateFieldDocumentation(AbstractFieldsSnippet.java:176)
at org.springframework.restdocs.payload.AbstractFieldsSnippet.createModel(AbstractFieldsSnippet.java:100)
at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:64)
at org.springframework.restdocs.generate.RestDocumentationGenerator.handle(RestDocumentationGenerator.java:196)
at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:55)
at org.springframework.test.web.servlet.MockMvc.andDo(MockMvc.java:177)
at com.example.my.api.domain.MyRepositoryRestTest.findOne(MyRepositoryRestTest.java:36)

如何让 spring-restdocsspring-data-rest 玩得开心?


编辑(小号):

我的documentation实例定义如下:

ResultHandler documentation = document("items/findOne",
                                       preprocessRequest(prettyPrint(), maskLinks()),
                                       preprocessResponse(prettyPrint()),
                                       responseFields(
                                            fieldWithPath("name").description("Item name.")
                                            // Bunch more
                                       ));

正如@meistermeier 指出的那样,(在 the restdocs docs for ignoring links 之后,我可以添加

links(linkWithRel("self").ignored(),
      linkWithRel("_self").ignored().optional()) // docs suggest this. /shrug

但这仍然给我留下了:

SnippetException:未记录具有以下关系的链接:[item]

似乎 _links 总是会将自我引用返回到同一个实体,对吧? 我如何在不忽略每个测试的实体特定 link 的情况下干净地处理这个问题,例如:

links(linkWithRel("item").ignored())

即使我 do 添加上面的行(这样所有字段 self _self curiesitem 都是all ignored() and/or optional()), 测试的结果returns 到本题顶部的原始错误。

Seems like the _links are always going to have that self-reference back to the same entity, right?

是的,没错。

我可能有您忽略 a small github sample 中某些 link 的解决方案。特别是部分:

mockMvc.perform(RestDocumentationRequestBuilders.get(beerLocation)).andExpect(status().isOk())
       .andDo(document("beer-get", links(
                linkWithRel("self").ignored(),
                linkWithRel("beerapi:beer").description("The <<beers, Beer resource>> itself"),
                linkWithRel("curies").ignored()
               ),
               responseFields(
                  fieldWithPath("name").description("The name of the tasty fresh liquid"),
                  fieldWithPath("_links").description("<<beer-links,Links>> to other resources")
               )
            ));

我完全忽略所有 "generated" 字段,只为该域创建一个文档条目。你的 item link 就是我的 beerapi:beer.

我真的不知道这里的最佳实践是什么,但我总是会尽可能多地记录,因为您可以尽可能使用 asciidoctor links(如 <<beer-links,Links>>)来参考其他包含更多文档的部分。

规范的方式似乎是使用 restdocs 文档中的东西。方法与 https://whosebug.com/users/2650436/meistermeier 解决方案中的方法一致。

可以在 https://docs.spring.io/spring-restdocs/docs/current/reference/html5/#documenting-your-api-hypermedia-link-formats

上找到文档

示例代码:

.consumeWith(document("items",
       links(
               halLinks(), // <- this shorten things a bit
               linkWithRel("self").ignored(),
               linkWithRel("profile").ignored()
       ),