相关文章推荐
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

With just simple following controller action spock integration-test. Here is my Test.

@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

getting following Exception

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)
                Can you add the full actual test class and the controller under test to the question as well?
– dmahapatro
                Jul 4, 2015 at 15:53

Unfortunately it might be a limitation in Grails 3, that you cannot use integration tests to test controllers.

To integration test controllers it is recommended you use create-functional-test command to create a Geb functional test.

Source from Grails documentation

This seems to be a major change of direction from previous versions of grails. If you really need to test a controller in an integration test, you could try doing this:

NOTE: I realize this might be a bad practice, and it goes against Grails documentation, but sometimes you also need to test things more programmatically, where unit tests aren't sufficient, and are Geb tests aren't granular enough.

@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

WARNING: After some additional work with this format I did find a problem. Using @TestFor will call Holders.clear() when it is complete, which means that there will not be a grailsApplication object in Holders. This will cause problems if you have any integration tests that run after one that uses the approach above. After much digging, it doesn't look like there is an easy (or even hard) way of making this work, which is possibly why it is not supported in Grails 3. That being said, one option is to mark other integration tests with @TestFor, so that the Holders class will be properly populated. Is this a hack? Yes it is! You will need to decide if it is worth the effort of adding this overhead to all tests. In my case it was only one other integration test that needed this (as it is a small application), but if it was more than that I would not use this approach.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.

 
推荐文章