코드 그라데이션
230217 BoardServiceImpl 테스트 코드 (2) 게시글 수정 성공 / 실패 본문
초안
@Test
@DisplayName("게시글 업데이트 성공 테스트")
void updateBoard() {
// given
User user = mock(User.class);
Board board = mock(Board.class);
BoardRequestDto boardRequestDto = mock(BoardRequestDto.class);
when(boardRepository.findById(board.getId())).thenReturn(Optional.of(board));
when(Optional.of(board).get().checkBoardWriter(user)).thenReturn(true);
// 이 두 줄은 깡통에게 "이런 질문이 오면 무조건 이렇게 대답해" 하고 명령을 넣어놓는 것.
// when
boardService.updateBoard(board.getId(), boardRequestDto, user);
// then
verify(board).update(boardRequestDto);
}
부연설명
여기도 마찬가지
일단 내가 모르겠는 부분을 좀 보자
when(Optional.of(board).get().checkBoardWriter(user)).thenReturn(true);
이거
1. when(Optional.of(board)
2. .get().checkBoardWriter(user))
3. .thenReturn(true);
이렇게 뜻어볼 수 있음.
즉,
Optional<Board> board1 = Optional.of(board); //보드를 옵셔널로 감쌌다.
Board board2 = board1.get() //거기서 다시 보드를 얻었고
// 다시 감싼 걸 없앤 것. 즉, +5 후 -5 한 것이라고 생각하면 된다.
따라서
when(Optional.of(board).get().checkBoardWriter(user)).thenReturn(true); 자체를
when(board.get().checkBoardWriter(user)).thenReturn(true); 라고 써도 된다.
board2.checkBoardWriter(user);
// cf. 옵셔널은 객체를 한 번 감싼 것, 즉 객체가 null이라고 하더라도 감싼 것에 물어보니까
// 감싸고 있는 것은 절대 null이 아니기 때문에, nullPointException이 나지 않음.
지금 반환값이 void니까, assertThat으로 확인이 불가능하지.
그렇다면 board.update(boardRequestDto); 요 객체를 직접 확인해보는 방법을 쓰자.
그럼 board를 mocking 보다는 그냥 만들어주는게 테스트 확인에서는 더 보기 편안할 것 같아.
보드를 만들 때 필수요소인 title, content, subject는 반드시 있어야겠지.
@Test
@DisplayName("게시글 업데이트 성공 테스트")
void updateBoard() {
// given
User user = mock(User.class);
Board board = Board.builder()
.title("test-title")
.content("test-content")
.subject(Board.BoardSubject.동네소식)
.user(user)
.build();
// 그런데 테스트가 되려면 Dto까지 값이 있어야겠죠. 내가 확인하고 싶은 값이니까
// title을 반드시 바꿔야해요.
BoardRequestDto boardRequestDto = BoardRequestDto.builder()
.title("after-title")
.content("after-content")
.subject(Board.BoardSubject.공지사항)
.build();
// 이건 잘 되어 있고,
when(boardRepository.findById(board.getId())).thenReturn(Optional.of(board));
// board는 이제 더이상 mock 객체가 아니므로 이 문장은 불가능해졌음
// when(board.get().checkBoardWriter(user)).thenReturn(true);
// 하지만 위에서 user을 넣어줬고, //when에서 똑같은 user을 업데이트 하라고 했기 때문에
// when에서 이 식이 true로 정상적으로 잘 수행이 될 것이다.
boardService.updateBoard(board.getId(), boardRequestDto, user);
// 이제 then으로 확인만 해주면 됨.
// then
assertThat(board.getTitle()).isEqualTo(boardRequestDto.getTitle());
assertThat(board.getContent()).isEqualTo(boardRequestDto.getContent());
assertThat(board.getSubject()).isEqualTo(boardRequestDto.getSubject());
이제 게시글 수정 실패 테스트 코드
BoardServiceImpl 코드 중에
if (!board.checkBoardWriter(user)) {
throw new IllegalArgumentException("본인 게시글이 아닙니다");
}
이 상황이 일어나게 만들면 된다!
=> 그렇게 되려면
board가 가진 user와 요청을 보내는 user가 다르기면 하면 된다.
여기서는 dto가 쓰이고 있긴 하지만, 이 테스트 자체는 board와 user에만 관심이 있는 것.
이럴 때는 dto내용을 없애거나 mocking을 하거나 값을 null 주면 된다.
@Test
@DisplayName("게시글 업데이트 실패 테스트 : 본인 게시글이 아닌 경우")
void updateBoard() {
// given
// 본인인지 아닌지 유저를 알아봐야하니까, just mocking 할 것이 아니라
// user를 직접 만들어서 비교해주는게 맞다.
// User user = mock(User.class);
유저 하나를 만들어주고,
// given
User userA = User.builder()
.username("userA")
.password("password1")
.build();
얘랑 다른 사용자 하나를 더 만들어 줘야 같은 사람이 아님을 비교할 수 있겠지.
User userB = User.builder()
.username("userB")
.password("password2")
.build();
게시글 생성 때는 UserA를 주고
Board board = Board.builder()
.title("test-title")
.content("test-content")
.subject(Board.BoardSubject.동네소식)
.user(userA)
.build();
when(boardRepository.findById(board.getId())).thenReturn(Optional.of(board);
/*
//when
업데이트 할 때는 userB를 준다
boardService.updateBoard(board.getId(), null, userB);
=> 여기까지 하면 "본인 게시글이 아닙니다" 메시지 뜨고 터지고 끝난다.
*/
예외처리 해줘야지
따라서 이렇게 수정해준다
// when
assertThatThrownBy(() -> {
boardService.updateBoard(board.getId(), null, userB); //예외가 발생하는 코드 삽입
}).isInstanceOf(IllegalArgumentException.class); // 결과. then
}
최종본
@Test
@DisplayName("게시글 업데이트 성공 테스트")
void updateBoard() {
// given
User user = mock(User.class);
Board board = Board.builder()
.title("test-title")
.content("test-content")
.subject(Board.BoardSubject.동네소식)
.user(user)
.build();
BoardRequestDto boardRequestDto = BoardRequestDto.builder()
.title("after-title")
.content("after-content")
.subject(Board.BoardSubject.공지사항)
.build();
when(boardRepository.findById(board.getId())).thenReturn(Optional.of(board));
// when
boardService.updateBoard(board.getId(), boardRequestDto, user);
// then
assertThat(board.getTitle()).isEqualTo(boardRequestDto.getTitle());
assertThat(board.getContent()).isEqualTo(boardRequestDto.getContent());
assertThat(board.getSubject()).isEqualTo(boardRequestDto.getSubject());
// verify(board).update(boardRequestDto);
}
@Test
@DisplayName("게시글 업데이트 실패 테스트: 본인 게시글이 아닌 경우")
void failsUpdateBoard() {
// given
User userA = User.builder()
.username("userA")
.password("password1")
.build();
User userB = User.builder()
.username("userB")
.password("password2")
.build();
Board board = Board.builder()
.title("test-title")
.content("test-content")
.subject(Board.BoardSubject.동네소식)
.user(userA)
.build();
when(boardRepository.findById(board.getId())).thenReturn(Optional.of(board));
// when
assertThatThrownBy(() -> {
boardService.updateBoard(board.getId(), null, userB);
}).isInstanceOf(IllegalArgumentException.class);
}
-1:13
728x90
'Spring > Test Code' 카테고리의 다른 글
230217 BoardServiceImpl 테스트 코드 (4) 게시글 삭제 (0) | 2023.02.28 |
---|---|
230217 BoardServiceImpl 테스트 코드 (3) 게시글 조회 (0) | 2023.02.27 |
230217 BoardServiceImpl 테스트 코드 (1) 게시글 생성 - 비교 (0) | 2023.02.26 |
230217 Service단 TestCode 전후 비교 (0) | 2023.02.26 |
20230210 테스트 코드 추가 설명 (4) 프로필 정보 조회 실패 테스트 (0) | 2023.02.16 |
Comments