是否可以直接在 grails 中使用 Spring MVC Test,如何使用?

is it possible to use Spring MVC Test directly in grails, and how?

我们认为 Spring Rest Doc 非常适合记录其余部分 api。但是它是基于Spring MVC Test的,我们无法弄清楚如何在我的grails应用程序(Grails 3.0.5)中使用Spring MVC Test

我尝试使用配置 class(使用 @Configuration@ComponentScan)将 grails 组件扫描到测试上下文中,但似乎没有加载任何内容(执行时对 mockmvc 的 http 请求,结果为 404)。

我也试过直接配置grails controller,结果出现运行时间错误。

Could not autowire field: private reactor.bus.EventBus

我也尝试在测试 class 中添加 @Integration(来自 grails),但收到了同样的错误。

请帮忙。

这里有一些代码示例。 我尝试的是将配置 class 或 class 位置或 grails 控制器添加到下面测试 class 的 ContextConfiguration 中。而测试 class 本身基本上是遵循 spring rest doc 参考。

import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.restdocs.RestDocumentation;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration
//TODO how to scan Grails components into the test context
public class QuestionRestSpec {
@Rule
public final RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");
@Autowired
private WebApplicationContext context;

private MockMvc mockMvc;

@Before
public void setUp() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
            .apply(documentationConfiguration(this.restDocumentation))
            .build();
}
}

配置class(没用):

@Configuration
@EnableWebMvc
@ComponentScan
public class AskConfig {
}

不幸的是,似乎无法将 MockMvc 与 Grails 一起使用。调用 MockMvc.perform 失败:

HandlerMapping requires a Grails web request. Stacktrace follows:
java.lang.IllegalArgumentException: HandlerMapping requires a Grails web request
    at org.springframework.util.Assert.notNull(Assert.java:112) ~[spring-core-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.grails.web.mapping.mvc.UrlMappingsHandlerMapping.getHandlerInternal(UrlMappingsHandlerMapping.groovy:113) ~[grails-web-url-mappings-3.0.9.jar:3.0.9]
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:299) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.getHandler(DispatcherServlet.java:1120) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.test.web.servlet.TestDispatcherServlet.getHandler(TestDispatcherServlet.java:90) [spring-test-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:932) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [tomcat-embed-core-8.0.26.jar:8.0.26]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) [spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65) [spring-test-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [tomcat-embed-core-8.0.26.jar:8.0.26]
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167) [spring-test-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134) [spring-test-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:144) [spring-test-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    …

Spring REST Docs 1.1 will hopefully add support for REST Assured。这消除了对 MockMvc 的需要,相反,将允许通过在功能测试中对 运行 服务器进行 HTTP 调用来记录 API。

作为参考,这是我使用的 Spock 规范:

package com.example.notes

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import grails.test.mixin.integration.Integration
import grails.transaction.*
import org.junit.Rule;
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.restdocs.RestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext

import spock.lang.*

@Integration
@Rollback
class ApiDocumentationSpec extends Specification {

    @Rule
    public final RestDocumentation restDocumentation = new RestDocumentation("build/generated-snippets");

    @Autowired
    WebApplicationContext context

    MockMvc mockMvc

    def setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
                .apply(documentationConfiguration(this.restDocumentation)).build();
    }

    def cleanup() {

    }

    void "list notes"() {
        when:
            MvcResult result = this.mockMvc.perform(get("/notes")).andReturn()
        then:
            result.andExpect(status().isOk())
                .andDo(document("notes-list-example"));
    }
}