Skip to content

Instantly share code, notes, and snippets.

@bastman
Last active February 6, 2018 14:54
Show Gist options
  • Save bastman/a4c736e59076d6e2ca302d508c2b114a to your computer and use it in GitHub Desktop.
Save bastman/a4c736e59076d6e2ca302d508c2b114a to your computer and use it in GitHub Desktop.
spring testutils beanValidation (Kotlin) - How to construct a LocalValidatorFactoryBean (extends org.springframework.validation.Validator)
package com.example.testutils.beanvalidation
import org.hibernate.validator.HibernateValidator
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean
fun localValidatorFactoryBean():LocalValidatorFactoryBean {
val validator= LocalValidatorFactoryBean()
validator.setProviderClass(HibernateValidator::class.java)
validator.afterPropertiesSet()
return validator
}
// Example
@RunWith(MockitoJUnitRunner::class)
class SomeRequestHandlerTest {
private lateinit var handler: SomeRequestHandler
private val validator: Validator = localValidatorFactoryBean()
@Mock private lateinit var repoService: SomeRepoService
@Before
fun setup() {
handler = SomeRequestHandler(repoService=repoService, validator=validator)
}
}
package com.example.api.common
import org.springframework.validation.DataBinder
import org.springframework.validation.Validator
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
class BadRequestException(message: String) : RuntimeException(message)
fun <T : Any> validateBean(validator: Validator, value: T, beanName: String?): T {
val binder = if (beanName == null) {
DataBinder(value)
} else {
DataBinder(value, beanName)
}
binder.validator = validator
binder.validate()
val result = binder.bindingResult
if (!result.hasErrors()) {
return value
}
val errors = result.fieldErrors.map {
mapOf<String, Any?>(
"field" to "${it.objectName}.${it.field}",
"message" to it.defaultMessage
)
}
val classname: String = value::class.qualifiedName ?: value::class.toString()
val msg = "Failed to validate bean=$classname objectName: ${result.objectName} nestedPath: ${result.nestedPath} allErrors:${errors.joinToString("\n")}"
throw BadRequestException(msg)
}
// Example:
data class SomeRequest(
@get:[Min(1) Max(100)] val limit: Int,
@get:[Min(0) Max(1_000_000)] val offset: Int
)
@Component
class SomeHandler(private val validator:Validator) {
fun handle(req:SomeRequest):SomeResponse =
req
.let { validateBean(validator = validator, value = it, beanName = "request") }
.let { getSomeDataFromDb(it)}
.let { mapToResponse(it) }
private fun getSomeDataFromDb(req:SomeRequest):SomeDataFromDb
private fun mapToResponse(dataFromDb:SomeDataFromDb):SomeResponse
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment