[英]Documenting null values with Spring REST Docs
Let's say we have the following API: 假设我们有以下API:
@RestController
public class PersonController {
@GetMapping("/api/person")
public List<Person> findPeople() {
return Arrays.asList(new Person("Doe", "Foo", "John"), new Person("Doe", null, "Jane"));
}
}
Where the model class looks like this: 模型类如下所示:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String lastName;
private String middleName;
private String firstName;
}
As you can see in the controller, the middleName
property of the second object in the list is null
. 正如您在控制器中看到的那样,列表中第二个对象的
middleName
属性为null
。 I'm now trying to use Spring REST Docs to document the properties of the API, so I wrote the following test: 我现在正尝试使用Spring REST Docs来记录API的属性,因此我编写了以下测试:
@Test
public void findAllReturnsPeople() throws Exception {
mockMvc.perform(get("/api/person").accept(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.[0].firstName", is("John")))
.andExpect(jsonPath("$.[0].middleName", is("Foo")))
.andExpect(jsonPath("$.[0].lastName", is("Doe")))
.andExpect(jsonPath("$.[1].firstName", is("Jane")))
.andExpect(jsonPath("$.[1].middleName", nullValue()))
.andExpect(jsonPath("$.[1].lastName", is("Doe")))
.andDo(document("person-get", responseFields(
fieldWithPath("[].firstName").description("The given name of a person"),
fieldWithPath("[].middleName").description("The optionally given middle name of a person"),
fieldWithPath("[].lastName").description("The last- or family name of a person"))));
}
By using the responseFields()
and fieldWithPath()
properties, I'm trying to give a description to each field. 通过使用
responseFields()
和fieldWithPath()
属性,我试图对每个字段进行描述。 However, this approach fails for the middle name, throwing the following exception: 但是,对于中间名,此方法失败,并引发以下异常:
org.springframework.restdocs.snippet.SnippetException: Fields with the following paths were not found in the payload: [[].middleName]
at org.springframework.restdocs.payload.AbstractFieldsSnippet.validateFieldDocumentation(AbstractFieldsSnippet.java:257)
at org.springframework.restdocs.payload.AbstractFieldsSnippet.createModel(AbstractFieldsSnippet.java:167)
at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:83)
at org.springframework.restdocs.generate.RestDocumentationGenerator.handle(RestDocumentationGenerator.java:206)
at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:55)
at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:183)
at be.g00glen00b.apps.demoempty.DemoEmptyApplicationTests.findAllReturnsPeople(DemoEmptyApplicationTests.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
However, when I change the code and change the middle name of the second Person
object to "Bar"
, the error disappears, and the snippet is correctly generated. 但是,当我更改代码并将第二个
Person
对象的中间名称更改为"Bar"
,错误消失了,并且正确生成了代码段。
Additionally, when I remove the fieldWithPath("[].middleName")
code, and I run the test, I get the following exception: 此外,当我删除
fieldWithPath("[].middleName")
代码并运行测试时,出现以下异常:
org.springframework.restdocs.snippet.SnippetException: The following parts of the payload were not documented:
[ {
"middleName" : "Foo"
}, {
"middleName" : null
} ]
Which makes sense, since the middle name property isn't documented in that case. 这是有道理的,因为在这种情况下没有记录中间名属性。
My question is how can I prevent this error and document what the middleName
property does? 我的问题是如何防止此错误并记录
middleName
属性的作用?
This is what I tried so far: 这是我到目前为止尝试过的:
[0].middleName
(this leads to the same exception) [0].middleName
(这导致相同的异常) JsonFieldType.STRING
or JsonFieldType.VARIES
(this also leads to the same exception) JsonFieldType.STRING
或JsonFieldType.VARIES
(这也会导致相同的异常) You need to tell REST Docs that the field is optional. 您需要告诉REST文档该字段是可选的。 You can do this by calling the
optional()
method on the FieldDescriptor
: 您可以通过在
FieldDescriptor
上调用optional()
方法来实现:
.andDo(document("person-get", responseFields(
fieldWithPath("[].firstName").description("The given name of a person"),
fieldWithPath("[].middleName").description("The optionally given middle name of a person").optional(),
fieldWithPath("[].lastName").description("The last- or family name of a person"))));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.