使用Spek进行WebFlux路由器的单元测试

时间:2018-06-20 18:19:02

标签: kotlin spring-webflux spek

我已经与Kotlin一起使用Spring的WebFlux框架了大约一个月,并且一直很喜欢它。当我准备深入学习使用WebFlux和Kotlin编写生产代码时,我发现自己正在努力以简单,轻便的方式对路由器进行单元测试。

Spring Test是一个出色的框架,但是它比我想要的要重,我一直在寻找一个比传统JUnit更具表现力的测试框架。 JavaScript的Mocha的某些东西。 Kotlin的Spek非常合适。

以下是我如何使用Spek单元测试简单路由器的示例。

1 个答案:

答案 0 :(得分:0)

WebFlux使用Kotlin的DSL定义了出色的Type-Safe Builders来构建路由器。虽然语法非常简洁易读,但如何断言它返回的路由器功能bean是否已正确配置(因为客户端代码通常无法访问其属性),尚不容易清楚。

说我们有以下路由器:

@Configuration
class PingRouter(private val pingHandler: PingHandler) {
    @Bean
    fun pingRoute() = router {
        accept(MediaType.APPLICATION_JSON).nest {
            GET("/ping", pingHandler::handlePing)
        }
    }
}

我们要断言,当传入的请求与/ping内容标头的application/json路由匹配时,该请求将传递给我们的处理函数。

object PingRouterTest: Spek({
    describe("PingRouter") {
        lateinit var pingHandler: PingHandler
        lateinit var pingRouter: PingRouter

        beforeGroup {
            pingHandler = mock()

            pingRouter = PingRouter(pingHandler)
        }

        on("Ping route") {
            /*
                We need to setup a dummy ServerRequest who's path will match the path of our router,
                and who's headers will match the headers expected by our router.
             */
            val request: ServerRequest = mock()
            val headers: ServerRequest.Headers = mock()

            When calling request.pathContainer() itReturns PathContainer.parsePath("/ping")
            When calling request.method() itReturns HttpMethod.GET
            When calling request.headers() itReturns headers
            When calling headers.accept() itReturns listOf(MediaType.APPLICATION_JSON)

            /*
                We call pingRouter.pingRoute() which will return a RouterFunction. We then call route()
                on the RouterFunction to actually send our dummy request to the router. WebFlux returns
                a Mono that wraps the reference to our PingHandler class's handler function in a
                HandlerFunction instance if the request matches our router, if it does not, WebFlux will
                return an empty Mono. Finally we invoke handle() on the HandlerFunction to actually call
                our handler function in our PingHandler class.
             */
            pingRouter.pingRoute().route(request).subscribe({ it.handle(request) })

            /*
                If our pingHandler.handlePing() was invoked by the HandlerFunction, we know we properly
                configured our route for the request.
             */
            it("Should call the handler with request") {
                verify(pingHandler, times(1)).handlePing(request)
            }
        }
    }
})