1

出于演示目的,我使用以下文件设置了一个全新的 grails 应用程序:

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
    }
}

当我到达http://localhost:8080/hallo时,“halloechen”被打印出来,因为它被设置为拦截器before()方法中的请求属性,就像我想要的那样。现在我想对拦截器进行单元测试:

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"
    }
}

此测试失败,因为该heading属性未设置为请求(无论如何这是一个模拟请求)。事实上,在运行单元测试时,拦截器似乎甚至没有被调用。我在before()方法中设置了一个断点,在调试测试时我从来没有到达那里。这很奇怪,因为我希望拦截器测试至少调用拦截器。我知道我可以按照这里的描述重写测试,但我的意思是拦截器根本不会被调用。那正确吗?另一件事:getModel()在测试中调用总是返回null。如何在我的测试中获得模型?

4

3 回答 3

1

如果这种情况持续存在,withInterceptors可能是因为https://github.com/grails/grails-testing-support/issues/29

一种解决方法是在真实的“加载拦截器测试”之前添加一个虚假的“加载拦截器测试”:

    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
    }
于 2020-07-09T17:23:23.357 回答
1

对我来说,诀窍是before()自己调用拦截器方法:

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"
    }
}
于 2019-02-06T09:33:26.203 回答
0

您需要使用该withInterceptors方法而不是withRequest- withRequest 仅验证匹配与否 - 因此拦截器从未实际运行。

从文档:

带有拦截器:

您可以使用 withInterceptors 方法在拦截器执行的上下文中执行代码。这通常用于调用依赖于拦截器行为的控制器动作

https://testing.grails.org/latest/guide/index.html

于 2019-02-05T16:50:18.883 回答