Last active
February 6, 2018 14:54
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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