4

カスタム Jackson モジュール (Spring Boot 1.3 を使用) を使用して、Spring REST ドキュメントに小さなテストを作成しました。私のアプリケーションのメインクラスには、@SpringBootApplication. JacksonCustomizations次に、次のような別のクラスがあります。

@Configuration
public class JacksonCustomizations {

@Bean
public Module myCustomModule() {
    return new MyCustomModule();
}

static class MyCustomModule extends SimpleModule {
    public MyCustomModule() {

        addSerializer(ImmutableEntityId.class, new JsonSerializer<ImmutableEntityId>() {
            @Override
            public void serialize(ImmutableEntityId immutableEntityId, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
                jsonGenerator.writeNumber( (Long)immutableEntityId.getId() );
            }
        });
    }
}
}

このカスタマイズは完璧にピックアップされています。Spring Boot アプリケーションを実行すると、本来あるべき JSON が表示されます。

ただし、ドキュメント テストでは、カスタマイズは適用されません。これは私のテストのコードです:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration
@WebAppConfiguration
public class NoteControllerDocumentation {

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

@Autowired
private WebApplicationContext context;

private MockMvc mockMvc;

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

}


@Test
public void notesListExample() throws Exception {
    mockMvc.perform(get("/api/notes/"))
           .andExpect(status().isOk())
           .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
           .andDo(document("notes-list-example", responseFields(
                   fieldWithPath("[]").description("An array of <<note-example,note>>s."))));
}

@Configuration
@EnableWebMvc
@Import(JacksonCustomizations.class)
public static class TestConfiguration {
    @Bean
    public NoteController noteController() {
        return new NoteController();
    }
}

}

テストのアプリケーション コンテキストがJacksonCustomizations構成をインポートする方法に注意してください。

私が見つけた他のもの:

  • @EnableWebMvcブート アプリケーションを追加すると、カスタマイズが機能しなくなります。
  • テストで を削除する@EnableWebMvcと、JSON の生成が停止します。
4

1 に答える 1

2

NoteControllerDocumentationSpring Boot を使用してアプリケーション コンテキストを作成するように構成されていません。これは、Spring Boot の自動構成が実行されないため、カスタム Jackson モジュールがObjectMapper.

問題の最も簡単な解決策は、クラスを削除し、代わりに参照にTestConfiguration更新することです。これにより、次のコードが残ります。SpringApplicationConfigurationDemoApplication

package com.example.controller;

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.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentation;
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.web.context.WebApplicationContext;

import com.example.DemoApplication;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
@WebAppConfiguration
public class NoteControllerDocumentation {

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

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

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

    }

    @Test
    public void notesListExample() throws Exception {
        mockMvc.perform(get("/api/notes/"))
               .andExpect(status().isOk())
               .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
               .andExpect(content().json("[{\"id\":1}]"))
               .andDo(print())
               .andDo(document("nodes-list-example", responseFields(
                       fieldWithPath("[]").description("An array of <<note-example,note>>s."))));
    }

}

または、コントロールの作成方法をさらに制御したい場合 (たとえば、モック サービスを挿入するため)、カスタム構成クラスを使用できます。@EnableAutoConfiguration重要なのは、Spring Boot の自動構成が有効になり、のカスタマイズが実行されるように、そのクラスにアノテーションを付けることObjectMapperです。このアプローチにより、次のコードが残ります。

package com.example.controller;

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.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentation;
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.web.context.WebApplicationContext;

import com.example.JacksonCustomizations;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration
@WebAppConfiguration
public class NoteControllerDocumentation {

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

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

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

    }

    @Test
    public void notesListExample() throws Exception {
        mockMvc.perform(get("/api/notes/"))
               .andExpect(status().isOk())
               .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
               .andExpect(content().json("[{\"id\":1}]"))
               .andDo(print())
               .andDo(document("nodes-list-example", responseFields(
                       fieldWithPath("[]").description("An array of <<note-example,note>>s."))));
    }

    @Configuration
    @EnableAutoConfiguration
    @Import(JacksonCustomizations.class)
    static class TestConfiguration {

        @Bean
        public NoteController notesController() {
            return new NoteController();
        }

    }

}
于 2015-12-09T10:17:08.390 に答える