5

只需简单的以下控制器动作 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)
4

2 回答 2

10

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

添加字段:

@Autowired
WebApplicationContext ctx

setup()GrailsWebMockUtil.bindMockWebRequest(ctx)

cleanup()RequestContextHolder.resetRequestAttributes()

于 2016-01-20T21:35:13.143 回答
4

不幸的是,这可能是 Grails 3 中的一个限制,您不能使用集成测试来测试控制器。

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

来自 Grails 文档的来源

与以前的 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
    }
}

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

于 2015-10-09T13:42:14.523 回答