2015-12-08 20 views
2

我已經寫了一個小測試Spring REST文檔與自定義傑克遜模塊(使用Spring Boot 1.3)。在我的應用程序主類中,我只有@SpringBootApplication。然後,我有另一個類JacksonCustomizations,看起來像這樣:自定義傑克遜模塊不使用在春季REST文檔測試

@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。
+0

您是否嘗試添加@Import(JacksonCustomizations.class)到NoteControllerDocumentation類? – reos

+0

@reos並沒有區別 –

+0

這聽起來像Spring Boot沒有自動配置'ObjectMapper'與您的自定義'模塊'。這符合你沒有爲你的應用程序提供'SpringApplicationConfiguration'類的事實,所以Spring Boot不知道該怎麼做。實際上,您共享的代碼由於這個原因而失敗,並且出現「IllegalStateException」,其中顯示「沒有在@SpringApplicationConfiguration中找到配置類或位置」。您是否可以分享一個小樣本項目,其中包含您正在運行的確切代碼以觸發問題? –

回答

1

NoteControllerDocumentation未配置爲使用Spring Boot來創建應用程序上下文。這意味着Spring Boot的自動配置不會運行,因此,您的自定義Jackson模塊不適用於ObjectMapper

解決您問題的最簡單方法是刪除TestConfiguration類,並將SpringApplicationConfiguration更新爲參考DemoApplication。這將離開你用下面的代碼:

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(); 
     } 

    } 

} 
+0

但是,如果我的控制器使用自動裝配的服務或存儲庫會怎麼樣?我怎樣才能爲它設置一個模擬?引用'DemoApplication'會注入真正的服務/回購。 –

+0

你沒有在問題中提到這個要求,所以我沒有解決它。我用另一種方法的細節更新了我的答案。 –