Skip to content

Commit ae53a4e

Browse files
committed
Allow request and path parameters to be marked as optional
Closes gh-169
1 parent ecdc197 commit ae53a4e

File tree

5 files changed

+64
-5
lines changed

5 files changed

+64
-5
lines changed

docs/src/docs/asciidoc/documenting-your-api.adoc

+3-2
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,8 @@ table describing the parameters that are supported by the resource.
348348

349349
When documenting request parameters, the test will fail if an undocumented request
350350
parameter is used in the request. Similarly, the test will also fail if a documented
351-
request parameter is not found in the request.
351+
request parameter is not found in the request and the request parameter has not been
352+
marked as optional.
352353

353354
If you do not want to document a request parameter, you can mark it as ignored. This will
354355
prevent it from appearing in the generated snippet while avoiding the failure described
@@ -396,7 +397,7 @@ built using one of the methods on `RestDocumentationRequestBuilders` rather than
396397

397398
When documenting path parameters, the test will fail if an undocumented path parameter
398399
is used in the request. Similarly, the test will also fail if a documented path parameter
399-
is not found in the request.
400+
is not found in the request and the path parameter has not been marked as optional.
400401

401402
If you do not want to document a path parameter, you can mark it as ignored. This will
402403
prevent it from appearing in the generated snippet while avoiding the failure described

spring-restdocs-core/src/main/java/org/springframework/restdocs/request/AbstractParametersSnippet.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,13 @@ protected Map<String, Object> createModel(Operation operation) {
8585

8686
private void verifyParameterDescriptors(Operation operation) {
8787
Set<String> actualParameters = extractActualParameters(operation);
88-
Set<String> expectedParameters = this.descriptorsByName.keySet();
88+
Set<String> expectedParameters = new HashSet<>();
89+
for (Entry<String, ParameterDescriptor> entry : this.descriptorsByName
90+
.entrySet()) {
91+
if (!entry.getValue().isOptional()) {
92+
expectedParameters.add(entry.getKey());
93+
}
94+
}
8995
Set<String> undocumentedParameters = new HashSet<>(actualParameters);
9096
undocumentedParameters.removeAll(expectedParameters);
9197
Set<String> missingParameters = new HashSet<>(expectedParameters);

spring-restdocs-core/src/main/java/org/springframework/restdocs/request/ParameterDescriptor.java

+24-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,8 @@ public class ParameterDescriptor extends IgnorableDescriptor<ParameterDescriptor
2929

3030
private final String name;
3131

32+
private boolean optional;
33+
3234
/**
3335
* Creates a new {@code ParameterDescriptor} describing the parameter with the given
3436
* {@code name}.
@@ -39,6 +41,16 @@ protected ParameterDescriptor(String name) {
3941
this.name = name;
4042
}
4143

44+
/**
45+
* Marks the parameter as optional.
46+
*
47+
* @return {@code this}
48+
*/
49+
public final ParameterDescriptor optional() {
50+
this.optional = true;
51+
return this;
52+
}
53+
4254
/**
4355
* Returns the name of the parameter being described by this descriptor.
4456
*
@@ -48,4 +60,15 @@ public final String getName() {
4860
return this.name;
4961
}
5062

63+
/**
64+
* Returns {@code true} if the described parameter is optional, otherwise
65+
* {@code false}.
66+
*
67+
* @return {@code true} if the described parameter is optional, otherwise
68+
* {@code false}
69+
*/
70+
public final boolean isOptional() {
71+
return this.optional;
72+
}
73+
5174
}

spring-restdocs-core/src/test/java/org/springframework/restdocs/request/PathParametersSnippetTests.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -71,6 +71,22 @@ public void ignoredPathParameter() throws IOException {
7171
"/{a}/{b}").build());
7272
}
7373

74+
@Test
75+
public void missingOptionalPathParameter() throws IOException {
76+
this.snippet
77+
.expectPathParameters(
78+
"missing-optional-path-parameter")
79+
.withContents(tableWithTitleAndHeader(
80+
this.templateFormat == TemplateFormats.asciidoctor() ? "/{a}"
81+
: "`/{a}`",
82+
"Parameter", "Description").row("a", "one").row("b", "two"));
83+
new PathParametersSnippet(Arrays.asList(parameterWithName("a").description("one"),
84+
parameterWithName("b").description("two").optional())).document(
85+
operationBuilder("missing-optional-path-parameter").attribute(
86+
RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE,
87+
"/{a}").build());
88+
}
89+
7490
@Test
7591
public void pathParametersWithQueryString() throws IOException {
7692
this.snippet.expectPathParameters("path-parameters-with-query-string")

spring-restdocs-core/src/test/java/org/springframework/restdocs/request/RequestParametersSnippetTests.java

+13
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ public void ignoredRequestParameter() throws IOException {
8080
.param("b", "bravo").build());
8181
}
8282

83+
@Test
84+
public void missingOptionalRequestParameter() throws IOException {
85+
this.snippet.expectRequestParameters("missing-optional-request-parameter")
86+
.withContents(tableWithHeader("Parameter", "Description").row("a", "one")
87+
.row("b", "two"));
88+
new RequestParametersSnippet(
89+
Arrays.asList(parameterWithName("a").description("one").optional(),
90+
parameterWithName("b").description("two"))).document(
91+
operationBuilder("missing-optional-request-parameter")
92+
.request("http://localhost").param("b", "bravo")
93+
.build());
94+
}
95+
8396
@Test
8497
public void requestParametersWithCustomAttributes() throws IOException {
8598
TemplateResourceResolver resolver = mock(TemplateResourceResolver.class);

0 commit comments

Comments
 (0)