2013-11-04 3 views
14

RESTコントローラのPOSTハンドラとの統合テストを行っています。まあ、私はしようとしています。REST POSTコントローラ:JSONを読み取れませんでした:入力の終了によりマップするコンテンツがありません

それは私にHttpMessageNotReadableException例外を与える:JSONを読み込むことができませんでした:原因ここで入力終了

にマップする内容は私のコントローラではありません:

@Controller 
@RequestMapping("admin") 
public class AdminController { 

    private static Logger logger = LoggerFactory.getLogger(AdminController.class); 

    private static final String TEMPLATE = "Hello, %s!"; 

    @Autowired 
    private AdminService adminService; 

    @Autowired 
    private AdminRepository adminRepository; 

    @RequestMapping(value = "crud", method = RequestMethod.POST, produces = "application/json; charset=utf-8") 
    @ResponseBody 
    public ResponseEntity<Admin> add(@RequestBody Admin admin, UriComponentsBuilder builder) { 
     AdminCreatedEvent adminCreatedEvent = adminService.add(new CreateAdminEvent(admin.toEventAdmin())); 
     Admin createdAdmin = Admin.fromEventAdmin(adminCreatedEvent.getEventAdmin()); 
     HttpHeaders responseHeaders = new HttpHeaders(); 
     responseHeaders.add("Content-Type", "application/json; charset=utf-8"); 
     responseHeaders.setLocation(builder.path("/admin/{id}").buildAndExpand(adminCreatedEvent.getAdminId()).toUri()); 
     return new ResponseEntity<Admin>(createdAdmin, responseHeaders, HttpStatus.CREATED); 
    } 

    @ExceptionHandler(HttpMessageNotReadableException.class) 
    @ResponseBody 
    public String handleException(HttpMessageNotReadableException e) { 
     return e.getMessage(); 
    } 

} 

基本テストクラス:

@RunWith(SpringJUnit4ClassRunner.class) 
@WebAppConfiguration 
@ContextConfiguration(classes = { ApplicationConfiguration.class, WebSecurityConfig.class, WebConfiguration.class, WebTestConfiguration.class }) 
@Transactional 
public abstract class AbstractControllerTest { 

    @Autowired 
    private WebApplicationContext webApplicationContext; 

    @Autowired 
    private FilterChainProxy springSecurityFilterChain; 

    protected MockHttpSession session; 

    protected MockHttpServletRequest request; 

    protected MockMvc mockMvc; 

    @Before 
    public void setup() { 
     this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).addFilters(this.springSecurityFilterChain).build(); 
    } 

} 

統合テスト:

@Test 
public void testAdd() throws Exception { 
    HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + "mypassword"); 
    this.mockMvc.perform(
     post("/admin/crud").headers(httpHeaders) 
     .param("firstname", "Stephane") 
     .param("lastname", "Eybert") 
     .param("login", "stephane") 
     .param("password", "toto") 
    ).andDo(print()) 
    .andExpect(
     status().isOk() 
    ).andReturn(); 
} 

何コンソールログが言っている:

2013-11-04 19:31:23,168 DEBUG [HttpSessionSecurityContextRepository] SecurityContext stored to HttpSession: '[email protected]8ddda0: Authentication: org.springframew[email protected]158ddda0: Principal: [email protected]: Username: stephane; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ADMIN' 
2013-11-04 19:31:23,168 DEBUG [RequestResponseBodyMethodProcessor] Written [Could not read JSON: No content to map due to end-of-input 
at [Source: UNKNOWN; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input 
at [Source: UNKNOWN; line: 1, column: 1]] as "application/json;charset=utf-8" using [[email protected]d328] 
2013-11-04 19:31:23,169 DEBUG [TestDispatcherServlet] Null ModelAndView returned to DispatcherServlet with name '': assuming HandlerAdapter completed request handling 
2013-11-04 19:31:23,169 DEBUG [TestDispatcherServlet] Successfully completed request 
2013-11-04 19:31:23,169 DEBUG [ExceptionTranslationFilter] Chain processed normally 
2013-11-04 19:31:23,169 DEBUG [SecurityContextPersistenceFilter] SecurityContextHolder now cleared, as request processing completed 
MockHttpServletRequest: 
     HTTP Method = POST 
     Request URI = /admin/crud 
      Parameters = {firstname=[Stephane], lastname=[Eybert], login=[stephane], password=[toto]} 
      Headers = {Content-Type=[application/json], Accept=[application/json], Authorization=[Basic c3RlcGhhbmU6bXlwYXNzd29yZA==]} 

      Handler: 
       Type = com.thalasoft.learnintouch.rest.controller.AdminController 
       Method = public org.springframework.http.ResponseEntity<com.thalasoft.learnintouch.rest.domain.Admin> com.thalasoft.learnintouch.rest.controller.AdminController.add(com.thalasoft.learnintouch.rest.domain.Admin,org.springframework.web.util.UriComponentsBuilder) 

       Async: 
    Was async started = false 
     Async result = null 

    Resolved Exception: 
       Type = org.springframework.http.converter.HttpMessageNotReadableException 

     ModelAndView: 
      View name = null 
       View = null 
       Model = null 

      FlashMap: 
MockHttpServletResponse: 
       Status = 200 
     Error message = null 
      Headers = {Content-Type=[application/json;charset=utf-8], Content-Length=[254]} 
     Content type = application/json;charset=utf-8 
       Body = Could not read JSON: No content to map due to end-of-input 
at [Source: UNKNOWN; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input 
at [Source: UNKNOWN; line: 1, column: 1] 
     Forwarded URL = null 
     Redirected URL = null 
      Cookies = [] 
2013-11-04 19:31:23,177 DEBUG [TransactionalTestExecutionListener] No method-level @Rollback override: using default rollback [true] for test context [[email protected] testClass = AdminControllerTest, testInstance = [email protected], testMethod = [email protected], testException = [null], mergedContextConfiguration = [[email protected] testClass = AdminControllerTest, locations = '{}', classes = '{class com.thalasoft.learnintouch.rest.config.ApplicationConfiguration, class com.thalasoft.learnintouch.rest.config.WebSecurityConfig, class com.thalasoft.learnintouch.rest.config.WebConfiguration, class com.thalasoft.learnintouch.rest.config.WebTestConfiguration}', contextInitializerClasses = '[]', activeProfiles = '{}', resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.test.context.web.WebDelegatingSmartContextLoader', parent = [null]]] 

任意の手掛かり?

答えて

2

私は.PARAMを置き換える().content()1の賛成方法:

 post("/admin/crud").headers(httpHeaders) 
     .contentType(MediaType.APPLICATION_JSON) 
     .accept(MediaType.APPLICATION_JSON) 
     .content("{ \"firstname\" : \"" + admin0.getFirstname() + "\", \"lastname\" : \"" + admin0.getLastname() + "\", \"email\" : \"" + admin0.getEmail() + "\", \"login\" : \"" + admin0.getLogin() + "\", \"password\" : \"" + admin0.getPassword() + "\", \"passwordSalt\" : \"" + admin0.getPasswordSalt() + "\" }") 
    ).andDo(print()) 
    .andExpect(status().isCreated()) 
    .andExpect(jsonPath("$.firstname").value(admin0.getFirstname())) 
    .andExpect(jsonPath("$.lastname").value(admin0.getLastname())) 
    .andExpect(jsonPath("$.email").value(admin0.getEmail())) 
    .andExpect(jsonPath("$.login").value(admin0.getLogin())) 
    .andExpect(jsonPath("$.password").value(admin0.getPassword())) 
    .andExpect(jsonPath("$.passwordSalt").value(admin0.getPasswordSalt())) 
    .andReturn(); 

これは期待どおりに動作します。

+0

あなたの答えを正しい答えとして記入してください。 – clemp6r

9

私の意見では、問題はコンテンツフォーマットにあります。あなたのエンドポイントは、データがアプリケーション/ JSONとして送信されますが、テストでは、あなたが(あなたがリクエストで適切なコンテンツタイプヘッダを設定することは重要ではありません)アプリケーション/ x-www-form-urlencodedでとして送信することを期待しています。 (リクエストのボディとして)JSON形式で管理オブジェクトを送信するようにしてください:

{ 
"firstname" : "Stephane", 
"lastname" : "Eybert", 
"login" : "stephane", 
"password" : "toto" 
} 

ところで/admin/crudは休耕RESTリソースルールに対処しません、あなたは/adminにそれを変更する必要があります。 CRUD(DELETE、、、UPDATEをREADをCREATE)(、POSTをGET、PUT、DELETE)HTTPメソッドにマップされます

+0

アドレッシングルールをお寄せいただきありがとうございます。確かに私はこの "荒れ狂う"名前を使用したくないが、何を持っているのだろうかと思った。 @RequestMapping( "/ admin")パブリッククラスAdminControllerは、メソッドレベルでどのようなマッピングを行うべきか戸惑っていました。@RequestMapping(value = " @ResponseBody public ResponseEntity add(...) – Stephane

+0

@RequestMapping(method = RequestMethod。)を使うことができると思います。 POSTは、メソッドレベルで= "application/json; charset = utf-8")を生成します。メソッドを '/ admin'にバインドします – ragnor

+0

本当に、それはvalue属性がなくてもうまくいきます。ありがとう! – Stephane

関連する問題