Grails 3:单元测试拦截器:不会在拦截器中停止

Posted

技术标签:

【中文标题】Grails 3:单元测试拦截器:不会在拦截器中停止【英文标题】:Grails 3: Unit Testing Interceptors: Doesn't halt in interceptor 【发布时间】:2019-06-29 11:29:50 【问题描述】:

出于演示目的,我使用这些文件设置了一个全新的 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() 方法中设置了一个断点,在调试测试时我从来没有到达那里。这很奇怪,因为我希望拦截器测试至少调用拦截器。 我知道我可以按照here 的描述重写测试,但我的意思是拦截器根本不会被调用。 那正确吗?另一件事:在测试中调用getModel() 总是返回null。如何在我的测试中获取模型?

【问题讨论】:

【参考方案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
    

【讨论】:

【参考方案2】:

对我来说,诀窍是自己调用拦截器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"
    

【讨论】:

【参考方案3】:

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

来自文档:

withInterceptors:

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

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

【讨论】:

这对我不起作用,拦截器代码仍然没有被调用。

以上是关于Grails 3:单元测试拦截器:不会在拦截器中停止的主要内容,如果未能解决你的问题,请参考以下文章

Grails 3 在过滤器之前运行拦截器

Axios 中的单元测试拦截器逻辑

为什么我的拦截器在Weld SE单元测试中失败?

单元测试 Angular 12 HTTP 拦截器 expectOne 失败

单元测试怎么注入service

如何对这个从管道可观察到的错误捕获的 Angular 打字稿 Http 错误拦截器进行单元测试?