Grails3控制器集成测试用例失败:未找到线程绑定请求

时间:2015-07-04 13:37:13

标签: grails grails-plugin grails-3.0 integration-testing

只需简单的跟随控制器动作spock集成测试。这是我的测试。

@Integration
@Rollback
class TestControllerSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    void "test something"() {
       setup:
        def c = new TestController()
        c.index()
        expect:
        c.response.contentType !=null
    }
}

获得以下异常

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
    at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
    at grails.web.api.WebAttributes$Trait$Helper.currentRequestAttributes(WebAttributes.groovy:45)
    at grails.web.api.ServletAttributes$Trait$Helper.getRequest(ServletAttributes.groovy:42)

2 个答案:

答案 0 :(得分:10)

我一直这样做,似乎工作正常:

添加字段:

@Autowired
WebApplicationContext ctx

setup()中: GrailsWebMockUtil.bindMockWebRequest(ctx)

cleanup()中: RequestContextHolder.resetRequestAttributes()

答案 1 :(得分:4)

不幸的是,它可能是Grails 3中的限制,您无法使用集成测试来测试控制器。

  

要集成测试控制器,建议您使用   create-functional-test命令用于创建Geb功能测试。

Source from Grails documentation

这似乎是以前版本的grails方向的重大改变。如果您确实需要在集成测试中测试控制器,可以尝试这样做:

注意:我意识到这可能是一个不好的做法,它违反了Grails文档,但有时您还需要以编程方式进行更多测试,单元测试不充分,并且是Geb测试不够精确。

@TestFor(TestController) // This will provide a mocked "controller" reference
@Integration
@Rollback
class TestControllerSpec extends Specification {

    // If TestController uses any services, have them autowired into this test
    @Autowired
    SomeService someService

    def setupSpec() {
        // Now connect those services to the controller
        controller.someService = someService
    }

    void "test something"() {
        when:
        controller.index()

        then:
        response.contentType != null
    }
}

警告:使用此格式进行一些额外的工作后,我确实发现了一个问题。使用@TestFor会在Holders.clear()完成后调用grailsApplication,这意味着Holders中不会有@TestFor个对象。如果您使用上述方法之后运行的任何集成测试,这将导致问题。经过大量挖掘后,看起来似乎没有一种简单(甚至是很难)的方法来完成这项工作,这可能就是Grails 3不支持它的原因。尽管如此,一种选择是标记其他集成测试Holders,以便正确填充nix-shell . --command "zsh"类。 这是一个黑客?是的!是的!您需要决定是否值得为所有测试添加此开销。在我的情况下,只有一个其他集成测试需要这个(因为它是一个小应用程序),但如果它不止于此我就不会使用这种方法。