ハイパーメディア
Spring REST Docs は、ハイパーメディアベース [Wikipedia] (英語) の API でリンクをドキュメント化するためのサポートを提供します。次の例は、その使用方法を示しています。
MockMvc
WebTestClient
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class Hypermedia {
// Fields
private MockMvc mockMvc;
@Test
void test() throws Exception {
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("index", links((1)
linkWithRel("alpha").description("Link to the alpha resource"), (2)
linkWithRel("bravo").description("Link to the bravo resource")))); (3)
}
}| 1 | Spring REST ドキュメントを構成して、レスポンスのリンクを説明するスニペットを生成します。org.springframework.restdocs.hypermedia.HypermediaDocumentation で静的 links メソッドを使用します。 |
| 2 | rel が alpha であるリンクを期待します。org.springframework.restdocs.hypermedia.HypermediaDocumentation で静的 linkWithRel メソッドを使用します。 |
| 3 | rel が bravo であるリンクを期待します。 |
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
public class Hypermedia {
// Fields
private WebTestClient webTestClient;
@Test
void test() {
this.webTestClient.get()
.uri("/")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus()
.isOk()
.expectBody()
.consumeWith(document("index", links((1)
linkWithRel("alpha").description("Link to the alpha resource"), (2)
linkWithRel("bravo").description("Link to the bravo resource")))); (3)
}
}| 1 | Spring REST ドキュメントを構成して、レスポンスのリンクを説明するスニペットを生成します。org.springframework.restdocs.hypermedia.HypermediaDocumentation で静的 links メソッドを使用します。 |
| 2 | rel が alpha であるリンクを期待します。org.springframework.restdocs.hypermedia.HypermediaDocumentation で静的 linkWithRel メソッドを使用します。 |
| 3 | rel が bravo であるリンクを期待します。 |
その結果、リソースのリンクを説明するテーブルを含む links.adoc という名前のスニペットが作成されます。
レスポンス内のリンクに title がある場合、記述子から説明を省略でき、title が使用されます。説明を省略し、リンクに title がない場合、エラーが発生します。 |
リンクをドキュメント化する場合、ドキュメント化されていないリンクがレスポンスで見つかった場合、テストは失敗します。同様に、ドキュメント化されたリンクがレスポンスに見つからず、リンクがオプションとしてマークされていない場合も、テストは失敗します。
リンクをドキュメント化したくない場合は、無視するようにマークできます。そうすることで、上記の失敗を回避しながら、生成されたスニペットに表示されなくなります。
ドキュメント化されていないリンクがテストの失敗を引き起こさない、緩和モードでリンクをドキュメント化することもできます。これを行うには、org.springframework.restdocs.hypermedia.HypermediaDocumentation で relaxedLinks メソッドを使用します。これは、リンクのサブセットのみに注目したい特定のシナリオをドキュメント化する場合に役立ちます。
ハイパーメディアリンク形式
デフォルトでは、次の 2 つのリンク形式が認識されます。
原子: リンクは
linksという名前の配列にあると予想されます。これは、レスポンスのコンテンツ型がapplication/jsonと互換性がある場合にデフォルトで使用されます。HAL: リンクは
_linksという名前のマップにあると予想されます。これは、レスポンスのコンテンツ型がapplication/hal+jsonと互換性がある場合にデフォルトで使用されます。
Atom または HAL 形式のリンクを使用するが、コンテンツ型が異なる場合は、組み込みの LinkExtractor 実装の 1 つを links に提供できます。次の例は、その方法を示しています。
MockMvc
WebTestClient
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.halLinks;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
class HypermediaWithSpecificExtractor {
// Fields
private MockMvc mockMvc;
@Test
void explicitExtractor() throws Exception {
this.mockMvc.perform(get("/").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("index", links(halLinks(), (1)
linkWithRel("alpha").description("Link to the alpha resource"),
linkWithRel("bravo").description("Link to the bravo resource"))));
}
}org.springframework.restdocs.hypermedia.HypermediaDocumentation で静的 halLinks メソッドを使用します。
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.halLinks;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.links;
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
class HypermediaWithSpecificExtractor {
// Fields
private WebTestClient webTestClient;
@Test
void test() {
this.webTestClient.get()
.uri("/")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus()
.isOk()
.expectBody()
.consumeWith(document("index", links(halLinks(), (1)
linkWithRel("alpha").description("Link to the alpha resource"),
linkWithRel("bravo").description("Link to the bravo resource"))));
}
}org.springframework.restdocs.hypermedia.HypermediaDocumentation で静的 halLinks メソッドを使用します。
API が Atom または HAL 以外の形式でリンクを表す場合、LinkExtractor インターフェースの独自の実装を提供して、レスポンスからリンクを抽出できます。
共通リンクを無視する
HAL を使用する場合の self や curies など、すべてのレスポンスに共通するリンクをドキュメント化するのではなく、概要セクションで一度ドキュメント化してから、残りの API ドキュメントで無視することをお勧めします。そのために、スニペットを再利用するためのサポートを構築して、特定のリンクを無視するように事前構成されたスニペットにリンク記述子を追加できます。次の例は、その方法を示しています。
import org.springframework.restdocs.hypermedia.HypermediaDocumentation;
import org.springframework.restdocs.hypermedia.LinkDescriptor;
import org.springframework.restdocs.hypermedia.LinksSnippet;
import static org.springframework.restdocs.hypermedia.HypermediaDocumentation.linkWithRel;
final class Hypermedia {
// @fold: on
private Hypermedia() {
}
// @fold: off
static LinksSnippet ignoreSelfAndCuries(LinkDescriptor... descriptors) {
return HypermediaDocumentation.links(linkWithRel("self").ignored().optional(), linkWithRel("curies").ignored())
.and(descriptors);
}
}