spring-restdocs
spring-restdocs copied to clipboard
Document how to use Spring REST Docs with the MockMVC Kotlin DSL
Was trying to implement RestDocs MockMvc in our Kotlin project However noticed that when using the MockMvc Kotlin DSL snippets were not generated e.g.
fun shouldReturnDefaultMessageKotlinDSL() {
mockMvc.get("/hello")
.andExpect {
status { isOk }
content {
string(containsString("Hello, world!"))
}
}.andDo {
print()
document("home")
}
}
However using the java format did correctly generate e.g.
fun shouldReturnDefaultMessage() {
this.mockMvc.perform(get("/hello"))
.andDo(print())
.andExpect(status().isOk)
.andExpect(content().string(containsString("Hello, world!")))
.andDo(document("home"))
}
Thanks for the report. REST Docs doesn't contain any Kotlin-specific code so I suspect that this is a problem with the MockMvc Kotlin DSL rather than REST Docs. To help us to figure out if that's the case, can you please provide a complete and minimal sample that reproduces the problem? You can do so by zipping something up and attaching it to this issue or by pushing it to a separate repository.
Hi wilkinsona, have uploaded example to repo here: https://github.com/seanyyyyyy/spring-cloud-kotlin-producer/blob/master/src/test/kotlin/com/example/cloudkotlin/testingrestdocs/RestdocsHelloControllerTest.kt
Thanks for the sample. When using the Kotlin DSL for MockMvc, you need to pass the result handler that is returned from document(…)
to handle(ResultHandler)
:
@Test
fun shouldReturnDefaultMessageKotlinDSL() {
mockMvc.get("/hello")
.andExpect {
status { isOk }
content {
string(containsString("Hello, World"))
}
}.andDo {
print()
handle(document("home"))
}
}
It's a shame that for this one piece, the Kotlin DSL isn't quite as elegant as the Java equivalent. I'm not sure how it could be improved while keeping the existing more elegant access to the built-in result handlers such as print()
. @sdeleuze any suggestions here?
I'll keep this issue open as I think it's worth documenting the above.
@wilkinsona Looks like there might be another issue with url templates. I'm seeing the following exception when using url templates in the request:
urlTemplate not found. If you are using MockMvc did you use RestDocumentationRequestBuilders to build the request?
java.lang.IllegalArgumentException: urlTemplate not found. If you are using MockMvc did you use RestDocumentationRequestBuilders to build the request?
at org.springframework.util.Assert.notNull(Assert.java:201)
at org.springframework.restdocs.request.PathParametersSnippet.extractUrlTemplate(PathParametersSnippet.java:126)
at org.springframework.restdocs.request.PathParametersSnippet.extractActualParameters(PathParametersSnippet.java:113)
at org.springframework.restdocs.request.AbstractParametersSnippet.verifyParameterDescriptors(AbstractParametersSnippet.java:89)
at org.springframework.restdocs.request.AbstractParametersSnippet.createModel(AbstractParametersSnippet.java:74)
at org.springframework.restdocs.request.PathParametersSnippet.createModel(PathParametersSnippet.java:98)
at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:78)
at org.springframework.restdocs.generate.RestDocumentationGenerator.handle(RestDocumentationGenerator.java:191)
at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:52)
at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:201)
at org.springframework.test.web.servlet.MockMvcResultHandlersDsl.handle(MockMvcResultHandlersDsl.kt:63)
at com.exmaple.docs.DocTest$getTests$5.invoke(DocTest.kt:10)
But adding requestAttr(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/hello/{name}
) fixes it, but not a great solution.
@Test
fun shouldReturnDefaultMessageKotlinDSL() {
mockMvc.get("/hello/{name}", name) {
requestAttr(RestDocumentationGenerator.ATTRIBUTE_NAME_URL_TEMPLATE, "/hello/{name}")
}.andExpect {
status { isOk }
content {
string(containsString("Hello, World"))
}
}.andDo {
print()
handle(document("home"))
}
}
@countableSet Yeah, that's not great. Unfortunately, the Kotlin DSL hardcodes the use of MockMvcRequestBuilders
so that may be the best that can be done at the moment.
@sdeleuze, do you have any recommendations here please?
Sorry for the delay of my response.
It's a shame that for this one piece, the Kotlin DSL isn't quite as elegant as the Java equivalent. I'm not sure how it could be improved while keeping the existing more elegant access to the built-in result handlers such as print(). @sdeleuze any suggestions here?
You could probably extend MockMvc DSL in Spring REST Docs with something like:
fun MockMvcResultHandlersDsl.document(identifier: String, vararg snippets: Snippet) {
handle(MockMvcRestDocumentation.document(identifier, *snippets))
}
@countableSet Yeah, that's not great. Unfortunately, the Kotlin DSL hardcodes the use of MockMvcRequestBuilders so that may be the best that can be done at the moment.
@sdeleuze, do you have any recommendations here please?
Let's maybe discuss that in https://github.com/spring-projects/spring-restdocs/issues/547#issuecomment-812611417.