2015-07-04 5 views
5

Mit nur einfachen folgenden Controller-Aktion spock Integrationstest. Hier ist mein Test.Grails3-Controller-Integrationstest Fall fehlgeschlagen: Keine Thread-gebundene Anfrage gefunden

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

immer folgende Ausnahme

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) 
+0

Können Sie Fügen Sie die vollständige tatsächliche Testklasse und den zu testenden Controller zum q hinzu Frage auch? – dmahapatro

+0

@dmahapatro Ich habe meine Frage aktualisiert. – user1071671

Antwort

4

Leider könnte es eine Begrenzung in Grails 3 sein, dass Sie nicht Integrationstests Test-Controller verwenden können.

Für Integrationstestcontroller wird empfohlen, den Befehl create-functional-test zu verwenden, um einen Geb-Funktionstest zu erstellen.

Source from Grails documentation

Dies scheint aus früheren Versionen von Grails eine wesentliche Änderung der Richtung. Wenn Sie wirklich einen Controller in einem Integrationstest testen müssen, könnten Sie versuchen, dies zu tun:

HINWEIS: Ich weiß, dies könnte eine schlechte Praxis sein, und es geht gegen Grails Dokumentation, aber manchmal müssen Sie auch testen Dinge programmgesteuert, wo Komponententests nicht ausreichen, und Geb Tests sind nicht granular genug.

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

WARNUNG: Nach einiger zusätzlicher Arbeit mit diesem Format, das ich ein Problem gefunden haben. Mit @TestFor wird Holders.clear() aufgerufen, wenn es abgeschlossen ist, was bedeutet, dass kein Objekt in Holders sein wird. Dies führt zu Problemen, wenn Sie Integrationstests ausführen, die nach einem der oben genannten Verfahren ausgeführt werden. Nach vielem Graben sieht es nicht so aus, als ob es eine leichte (oder gar harte) Möglichkeit gibt, diese Arbeit zu machen, weshalb es möglicherweise in Grails 3 nicht unterstützt wird. Eine Möglichkeit ist es, andere Integrationstests mit zu markieren @TestFor, so dass die Klasse Holders korrekt ausgefüllt wird. Ist das ein Hack? Ja, so ist es! Sie müssen entscheiden, ob es sich lohnt, diesen Overhead für alle Tests zu verwenden. In meinem Fall war es nur ein weiterer Integrationstest, der dies benötigte (da es eine kleine Anwendung ist), aber wenn es mehr wäre, würde ich diesen Ansatz nicht verwenden.

9

Ich habe das getan, und es scheint gut zu funktionieren:

Feld hinzufügen:

@Autowired 
WebApplicationContext ctx 

In setup(): GrailsWebMockUtil.bindMockWebRequest(ctx)

In cleanup(): RequestContextHolder.resetRequestAttributes()

Verwandte Themen