For demo purposes I have set up a fresh grails application with these files:
class HalloController {
def index() {
String heading = request.getAttribute("heading")
render "${heading}"
}
}
class HalloInterceptor {
boolean before() {
request.setAttribute("heading", "halloechen") // *** set breakpoint here***
true
}
boolean after() { true }
void afterView() {
// no-op
}
}
When I got to http://localhost:8080/hallo "halloechen" gets printed as this was set as an request attribute in the interceptors before()
method, just like I wanted it to be. Now I want to have a unit test for the interceptor:
class HalloInterceptorSpec extends Specification implements InterceptorUnitTest<HalloInterceptor> {
def setup() {
}
def cleanup() {
}
void "Test hallo interceptor matching"() {
when:"A request matches the interceptor"
withRequest(controller:"hallo")
then:"The interceptor does match"
interceptor.doesMatch() && request.getAttribute("heading") == "halloechen"
}
}
This test fails as the heading
attribute does not get set to the request (which is a mocked request anyway). In fact, when running the unit test it seems as the interceptor doesn't even get called. I have set a breakpoint in the before()
method and when debugging the test I never get there. Which is odd because I would expect a Interceptor test to call the interceptor at least. I know I could rewrite the test as described here but my point is that the interceptor doesn't get called at all. Is that right? Another thing: calling getModel()
in the test alway returns null
. How do I get the model in my test?
The trick for me was calling the interceptors before()
method myself:
import grails.testing.web.interceptor.InterceptorUnitTest
import spock.lang.Specification
class HalloInterceptorSpec extends Specification implements InterceptorUnitTest<HalloInterceptor> {
def setup() {
}
def cleanup() {
}
void "Test hallo interceptor matching"() {
when: "A request matches the interceptor"
withRequest(controller: "hallo")
interceptor.before()
then: "The interceptor does match"
interceptor.doesMatch() && request.getAttribute("heading") == "halloechen"
}
}
If this persist with withInterceptors
it's probably because of https://github.com/grails/grails-testing-support/issues/29
A workaround is by adding a fake "loading interceptors test" before the real ones:
void "Fake test to load interceptor"() {
// this is necessary because of this: https://github.com/grails/grails-testing-support/issues/29
given:
def controller = (PostController) mockController(PostController)
when:
withInterceptors(controller: 'post') { true }
then:
true
}
You need to use the withInterceptors
method instead of the withRequest
- withRequest only validates matching or not - so the interceptor is never actually ran.
From the docs:
withInterceptors:
You can use the withInterceptors method to execute code within the context of interceptor execution. This is typically done to call controller actions that rely on behavior from interceptors .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.