@PutMapping에 대한 JUnit RestControllerTest에서 InvocationTargetException이 발생 함

Sep 14 2020

Spring Boot를 사용하여 마이크로 서비스를 구축하고 있습니다. GET-, POST-, PUT-, DELETE- 메서드로 API를 작성하고 응용 프로그램을 실행하고 Postman을 사용하여 테스트했습니다. 모든 것이 잘 작동합니다.

그러나 PUT-Method 테스트는 실패합니다.

java.lang.AssertionError : 예상 상태 : <204>이지만 다음과 같음 : <400>

디버그 모드 및 스테핑에서 테스트를 실행하면 InvocationTargetException이 발생합니다.

내 RestController-Methods는 다음과 같습니다.

@PutMapping(value = "/{id}")
public ResponseEntity updateSongById(@PathVariable("id") Integer id, @RequestBody @Validated 
SongDto songDto) {
    // TODO Add authorization
    SongDto song = songService.getSongById(id);
    if (song == null)
        return new ResponseEntity(HttpStatus.BAD_REQUEST);
    return new ResponseEntity(songService.updateSong(id, songDto), HttpStatus.NO_CONTENT);
}

songService.getSongById (id) :

@Override
public SongDto getSongById(Integer id) {
    return songMapper.songToSongDto(songRepository.findById(id)
        .orElseThrow(NotFoundException::new));
}

SongRepository는 JpaRepository <Song, Integer>를 확장하는 단순한 인터페이스입니다.

내 실패한 테스트는 다음과 같습니다.

@Test
void updateSongById_success() throws Exception {
    when(songService.updateSong(anyInt(), any(SongDto.class))).thenReturn(getValidSongDto());
    String songDtoJson = objectMapper.writeValueAsString(getValidSongDto());
    mockMvc.perform(put("/rest/v1/songs/1")
            .content(songDtoJson)
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isNoContent());
}

그리고 getValidSongDto ()는 내 테스트에 사용 된 Dto를 제공합니다.

private SongDto getValidSongDto() {
    return SongDto.builder()
            .id(1)
            .title("TestSongValid")
            .label("TestLabelValid")
            .genre("TestGenreValid")
            .artist("TestArtistValid")
            .released(1000)
            .build();
}

나는 지금까지이 테스트를 실패하게 만들기 위해 내가 뭘 잘못했는지 이해하지 못했으며 인터넷에서이 문제를 해결하는 데 도움이 된 것을 찾을 수 없었습니다. 그래서 누군가가 여기에서 무엇이 잘못되었는지,이 문제를 해결하는 방법을 말해 줄 수 있다면 매우 감사 할 것입니다.

대단히 감사합니다 !!

답변

2 SSK Sep 14 2020 at 21:02

songService.getSongById아래와 같이 값을 반환해야 합니다.

@Test
void updateSongById_success() throws Exception {
    
    when(songService.getSongById(Mockito.any())).thenReturn(getValidSongDto());
    
    when(songService.updateSong(anyInt(), any(SongDto.class))).thenReturn(getValidSongDto());
    
    String songDtoJson = objectMapper.writeValueAsString(getValidSongDto());
    
    mockMvc.perform(put("/rest/v1/songs/1")
            .content(songDtoJson)
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isNoContent());
}