Reputation: 8100
I'm attempting to validate a String
@PathVariable
inside a Kotlin Spring controller.
@RestController
@Validated
@RequestMapping("/kotlin/")
open class KStringController {
@GetMapping(path = ["string/{username}"],
produces = [APPLICATION_JSON_VALUE])
@ResponseBody
fun validateStringPathVariable(
@Pattern(regexp = "[A-Za-z]+", message = "Username Pattern Validation Message")
@Size(min = 2, max = 15, message = "Username Size Validation Message")
@PathVariable("username") username: String?
): ResponseEntity<String>? {
logger.info { String.format("validateStringPathVariable: Got Username [%s]", username) }
System.out.printf("validateStringPathVariable: Username is [%s]%n", username)
return ResponseEntity.ok("Username is valid")
}
}
I have unit tests for it:
@ExtendWith(SpringExtension::class)
@WebMvcTest(KStringController::class)
@AutoConfigureMockMvc
class KStringGetControllerTest {
@field:Autowired
private lateinit var mvc: MockMvc
@Test
@Throws(Exception::class)
fun validStringPathVariable() {
val request: MockHttpServletRequestBuilder = givenARequestFor("/kotlin/string/mike")
val actions: ResultActions = whenTheRequestIsMade(request)
thenExpect(actions,
MockMvcResultMatchers.status().isOk,
MockMvcResultMatchers.content().bytes("Username is valid".toByteArray()))
}
@Test
@Throws(Exception::class)
fun shoutsWhenStringPathVariableIsTooShort() {
val request = givenARequestFor("/kotlin/string/a")
val actions = whenTheRequestIsMade(request)
val response = """{
"validationErrors": [
{
"fieldName": "validateStringPathVariable.username",
"message": "Username Size Validation Message"
}
]
}"""
val content = MockMvcResultMatchers.content()
thenExpect(actions,
MockMvcResultMatchers.status().isBadRequest,
content.contentType(MediaType.APPLICATION_JSON),
content.json(response))
}
private fun givenARequestFor(url: String): MockHttpServletRequestBuilder {
return MockMvcRequestBuilders.get(url)
.characterEncoding("UTF-8")
}
@Throws(Exception::class)
private fun whenTheRequestIsMade(request: MockHttpServletRequestBuilder): ResultActions {
return mvc.perform(request)
}
@Throws(Exception::class)
private fun thenExpect(resultActions: ResultActions, vararg matchers: ResultMatcher) {
resultActions.andExpect(ResultMatcher.matchAll(*matchers))
}
Currently the second test is failing; it's returning a 200
response code when I'm expecting a 400
. Much much more code at https://github.com/Mavelous/spring-validation.
Upvotes: 0
Views: 1993
Reputation: 8100
With help from others, I've managed to find a solution.
Quick answer: Change the function to open fun validateStringPathVariable
, and the validations will start working.
Alternative answer: Use the org.jetbrains.kotlin.plugin.spring
plugin in your build.gradle
file.
I also created a blog post with a longer description: http://mavelo.us/2021/04/07/spring-validation-in-kotlin.html
Upvotes: 2