Можно ли использовать Spring MVC Test непосредственно в Grails и как?

Мы считаем, что Spring Rest Doc отлично подходит для документирования остальных API. Но он основан на Spring MVC Test, и мы не можем понять, как использовать Spring MVC Test в моих приложениях Grails (Grails 3.0.5).

Я попытался использовать класс конфигурации (с @Configuration и @ComponentScan) для сканирования компонентов Grails в тестовом контексте, но, похоже, ничего не было загружено (при выполнении http-запроса к mockmvc он получил 404).

Я также попытался настроить контроллер Grails напрямую и получил ошибку времени выполнения.

Не удалось автоподключить поле: частный Reactor.bus.EventBus

Я также пытался добавить @Integration (из Grails) в тестовый класс, но получил ту же ошибку.

Пожалуйста помоги.

Вот несколько примеров кода. я пытался добавить класс конфигурации или расположение классов или контроллер Grails в ContextConfiguration тестового класса ниже. И сам тестовый класс в основном следует ссылке 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();
}
}

Класс конфигурации (который бесполезен):

@Configuration
@EnableWebMvc
@ComponentScan
public class AskConfig {
}

person bitmountain    schedule 22.10.2015    source источник
comment
Какую версию Grails вы используете?   -  person Andy Wilkinson    schedule 22.10.2015
comment
я использую Grails 3.0.5   -  person bitmountain    schedule 22.10.2015
comment
Grails 3 — это просто приложение Spring Boot, так что, по крайней мере теоретически, это должно быть возможно, хотя, возможно, и не так, как в Grails. @Integration и я бы попробовал ввести ApplicationContext с помощью @Autowired. Можете ли вы поделиться своей попыткой сделать то, что не сработало?   -  person Andy Wilkinson    schedule 22.10.2015
comment
Я не совсем уверен, что вы подразумеваете под @Integration и внедрением ApplicationContext с помощью @Autowired. я обновил вопрос, добавив несколько примеров кода. По сути, он следует ссылке spring rest doc.   -  person bitmountain    schedule 23.10.2015


Ответы (1)


К сожалению, не представляется возможным использовать 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 мы надеемся добавить поддержку REST Assured. Это устраняет необходимость в MockMvc и вместо этого позволяет документировать API, выполняя HTTP-вызовы к работающему серверу в функциональном тесте.

Для справки, вот спецификация 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"));
    }
}
person Andy Wilkinson    schedule 23.10.2015