I'm trying to test a routerfunction in webmvc using kotest and mockk. I think the way it's written that only the router function and the test itself should be executed. Everything else is mocked. The routerfunction is configured as follows:
@Configuration
class DownloadRoutes(private val dnldCtrllr : DownloadController,
) {
private var baseUrl : String = "download"
@Bean
fun router(): RouterFunction<ServerResponse> {
return router {
baseUrl.nest{
accept(MediaType.TEXT_PLAIN).nest {
"/asset_request".nest {
POST(dnldCtrllr::downloadPost)
}
}
}
}
}
}
The test uses the WebMvcTest annotation. I mock the POST handler so that if it is called at it's entry point, it simply returns a status of OK.
The test looks as follows:
@WebMvcTest
@ContextConfiguration(classes = [DownloadRoutes::class])
class DownloadRoutesTest( @Autowired val mockMvc : MockMvc,
@MockkBean val mockDwnLd : DownloadController,
@Autowired val ctx : ApplicationContext
) : DescribeSpec({
describe("Download Service Routes") {
it("should route POSTs to the appropriate handler") {
val bean = ctx.getBean("router")
println(bean.toString())
every { mockDwnLd.downloadPost(any())} returns ServerResponse.status(HttpStatus.OK).build()
mockMvc.perform(MockMvcRequestBuilders
.post("/download/asset_request")
.accept(MediaType(MediaType.TEXT_PLAIN))
)
.andDo(MockMvcResultHandlers.print()) // prints the request and response; for debugging only
.andExpect(MockMvcResultMatchers.status().isOk)
}
}
})
It doesn't pass. I've printed the router bean obtained from the application context to be sure it's there and I think it looks right. I also added a print to the mockMvc chain so I can see what happens.
Here's the prints:
/download => {
Accept: text/plain => {
/asset_request => {
POST -> org.springframework.web.servlet.function.RouterFunctionDslKt$sam$org_springframework_web_servlet_function_HandlerFunction$0@1d9488b
GET -> org.springframework.web.servlet.function.RouterFunctionDslKt$sam$org_springframework_web_servlet_function_HandlerFunction$0@dca44a2
}
}
}
MockHttpServletRequest:
HTTP Method = POST
Request URI = /download/asset_request
Parameters = {}
Headers = [Accept:"text/plain"]
Body = null
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@3840636a}
Handler:
Type = null
MockHttpServletResponse:
Status = 403
Error message = Forbidden
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Status expected:<200> but was:<403>
Expected :200
Actual :403
I'm assuming that the 403 means it's never getting to the router function. Does the "handler = null" mean that the router is not getting invoked (why)? Does the mockMvc not properly deal with the router function (as opposed to the old annotation methods)? I'm assuming it's the mocked DownloadController that's getting injected into the DownloadRoutes, but I'm not entirely convinced.
Anyone have any thoughts?