728x90
이전글
목표
- 1. controller / 2. service로 나눠서 테스트를 진행해야 함.
- 1. 성공, 2. 실패 테스트 케이스를 모두 통과하는 실제 코드 작성.
- Exception 처리는 enum Error코드에 작성 후 호출 해서 사용
- 실패의 경우 enum값의 errorCode로 처리하기
- when(어떤 상황일 때)를 각각 설계해 보고, Test case에 따라 예상되는 결괏값을 작성해 주기
- Controller, Service 두 클래스의 테스트 코드 작성하기
체크사항
포스트 단건 조회(상세 보기)
service
- 조회 성공
포스트 등록
service
- 등록 실패 : 유저가 존재하지 않을 때
- 등록 성공
포스트 수정
service
- 수정 실패 : 포스트 존재하지 않음
- 수정 실패 : 작성자!=유저
- 수정 실패 : 유저 존재하지 않음
포스트 삭제
service
- 삭제 실패 : 유저 존재하지 않음
- 삭제 실패 : 포스트 존재하지 않음
Post Service Test
Basic
class PostServiceTest {
private PostService postService;
private PostRepository postRepository = mock(PostRepository.class);
private UserRepository userRepository = mock(UserRepository.class);
@BeforeEach
void setUp() {
postService = new PostService(postRepository, userRepository);
}
}
- 사용할 Repository를 mock을 사용하여 초기화시켜 줍니다.
- @BeforeEach를 사용해서 PostService에서 사용할 Repository를 초기화시킵니다.
포스트 단건 조회(상세 보기)
조회 성공
class PostServiceTest {
...
/* 포스트 상세 */
@Test
@DisplayName("조회 성공")
void success_get_post() {
Post fixture = PostFixture.get();
when(postRepository.findById(any())).thenReturn(Optional.of(fixture));
PostReadResponse response = postService.getPost(fixture.getId());
assertEquals(fixture.getUser().getUserName(), response.getUserName());
}
}
- postRepository의 findById를 사용하게 되면 Post 타입의 fixture를 반환하도록 설정했다.
- PostReadResponse에 getPost메서드를 사용해서 fixture의 postId를 사용하여 데이터를 저장받았다.
- fixture의 값과 response의 값이 동일한지 비교하였다.
포스트 등록
등록 성공
class PostServiceTest {
...
/* 포스트 등록 */
@Test
@DisplayName("등록 성공")
void success_post() {
User user = UserFixture.get("chordpli", "1234");
PostRequest request = new PostRequest("title", "body");
Post mockPost = mock(Post.class);
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user));
when(postRepository.save(any()))
.thenReturn(mockPost);
Assertions.assertDoesNotThrow(() -> postService.post(request, user.getUserName()));
}
- userId와 password를 넣어서 저장된 User값을 불러옵니다.
- Post를 작성하기 위한 request를 생성합니다.
- postRepository의 save메서드를 사용했을 때 반환받을 mock post를 생성합니다.
- userRepository의 findByUserName을 사용했을 때 user를 반환합니다.
- postRepository를 save 했을 때 mock으로 된 post를 반환합니다.
- postSerivce의 post를 진행했을 때 예외가 던져지지 않는다면 통과합니다.
등록 실패 - 유저가 존재하지 않을 때
class PostServiceTest {
...
/* 포스트 등록 */
@Test
@DisplayName("등록 실패_존재하지 않은 유저")
void fail_post_not_exist_user() {
User user = UserFixture.get("chordpli", "1234");
PostRequest request = new PostRequest("title", "body");
when(userRepository.findByUserName(user.getUserName())).thenReturn(Optional.empty());
SNSAppException exception
= Assertions.assertThrows(SNSAppException.class,
() -> postService.post(request, user.getUserName()));
Assertions.assertEquals(ErrorCode.USERNAME_NOT_FOUND, exception.getErrorCode());
}
}
- 저장되어있는 User 정보를 가지고 옵니다.
- Post를 작성하기 위한 request를 생성합니다.
- userRepository의 findByUserName을 실행했을 때 empty를 반환받습니다.
- assertThrows를 사용해서 post 메서드를 사용했을 때 SNSAppExcpeiont을 발생시킵니다.
- excpeiont이 발생한 error코드와 USERNAME_NOT_FOUND가 동일한지 확인합니다.
포스트 수정
수정 성공
class PostServiceTest {
...
/* 포스트 수정 */
@Test
@DisplayName("수정 성공")
void success_modify_post(){
Post fixture = PostFixture.get();
User user = UserFixture.get("chordpli", "1234");
when(postRepository.findById(any())).thenReturn(Optional.of(fixture));
when(userRepository.findByUserName(any())).thenReturn(Optional.of(user));
PostModifyRequest request = new PostModifyRequest("수정 제목", "수정 내용");
fixture.setTitle(request.getTitle());
fixture.setTitle(request.getBody());
when(postRepository.save(any()))
.thenReturn(fixture);
Assertions.assertDoesNotThrow(() -> postService.modifyPost(fixture.getId(), request, user.getUserName()));
assertEquals(fixture.getTitle(), request.getTitle());
}
}
- 저장된 Post와 User의 정보를 받아옵니다.
- postRepository의 findById를 사용하면 fixture를 반환받습니다.
- userRepository의 findByUserName을 사용하면 user를 반환받습니다.
- 수정할 내용을 받을 request를 생성합니다.
- fixture를 수정하고, postRespository의 save를 사용했을 때 수정된 fixture를 반환받습니다.
- postService.modify를 사용했을 때 예외가 발생하지 않으면 통과합니다.
- fixture의 title과 수정 요청된 title이 동일한지 확인합니다.
수정 실패 - 포스트가 존재하지 않을 때
class PostServiceTest {
...
/* 포스트 수정 */
@Test
@DisplayName("수정 실패_포스트가 존재하지 않음")
void fail_modify_post_not_exist_post() {
Post fixture = PostFixture.get();
when(userRepository.findByUserName(any())).thenReturn(Optional.of(mock(User.class)));
when(postRepository.save(any())).thenReturn(Optional.empty());
SNSAppException exception
= Assertions.assertThrows(SNSAppException.class,
() -> postService.modifyPost(fixture.getId(), new PostModifyRequest(fixture.getTitle(), fixture.getBody()), fixture.getUser().getUserName()));
Assertions.assertEquals(ErrorCode.POST_NOT_FOUND, exception.getErrorCode());
}
}
- 저장된 Post의 정보를 받아옵니다.
- userRepository의 findByUserName을 사용하면 mockUser를 반환합니다.
- postRepository의 save를 사용하면 empty를 반환합니다.
- post를 저장했을 때 해당 게시물이 존재하지 않으므로 예외를 발생시킵니다.
- exception의 에러코드가 POST_NOT_FOUND인지 확인합니다.
수정 실패 - 포스트의 작성자와 수정 요청을 보내는 유저가 다를 때
...
/* 포스트 수정 */
@Test
@DisplayName("수정 실패_작성자와 수정을 요청하는 유저가 다름")
void fail_modify_post_different_Requester_and_author() {
Post fixture = PostFixture.get();
User user = User.builder()
.id(2)
.userName("unknown")
.password("1111")
.userRole(UserRole.USER)
.build();
when(postRepository.findById(any())).thenReturn(Optional.of(new Post(fixture.getId(), fixture.getBody(), fixture.getTitle(), fixture.getUser())));
when(userRepository.findByUserName(any())).thenReturn(Optional.of(new User(user.getId(), user.getPassword(), user.getUserRole(), user.getUserName())));
SNSAppException exception
= Assertions.assertThrows(SNSAppException.class,
() -> postService.modifyPost(fixture.getId(), new PostModifyRequest(fixture.getTitle(), fixture.getBody()), fixture.getUser().getUserName()));
Assertions.assertEquals(ErrorCode.INVALID_PERMISSION, exception.getErrorCode());
}
}
- Post와 Post를 작성한 사람과 다른 새로운 User를 생성합니다.
- postRepository의 findById를 사용했을 때 Post 정보를 반환합니다.
- userRepository의 findByUserName을 사용했을때 User의 정보를 반환합니다.
- post의 user와 findByUserName으로 반환받은 User는 서로 다르기 때문에 예외를 발생시킵니다.
- exception의 에러코드가 INVALID_PERMISSION인지 확인합니다.
수정 실패 - 유저가 존재하지 않을 때
...
/* 포스트 수정 */
@Test
@DisplayName("수정 실패_유저가 존재하지 않음")
void fail_modify_post_not_exist_user() {
when(userRepository.findByUserName(any())).thenReturn(Optional.empty());
SNSAppException exception
= Assertions.assertThrows(SNSAppException.class,
() -> postService.modifyPost(fixture.getId(), new PostModifyRequest(fixture.getTitle(), fixture.getBody()), fixture.getUser().getUserName()));
Assertions.assertEquals(ErrorCode.USERNAME_NOT_FOUND, exception.getErrorCode());
}
}
- userRepository의 findByUserName을 사용했을 때 empty를 반환받습니다.
- 수정을 요청하려는 유저가 존재하지 않으므로 예외를 발생시킵니다.
- exception의 에러코드가 USERNAME_NOT_FOUND인지 확인합니다.
포스트 삭제
삭제 성공
class PostServiceTest {
...
/* 포스트 삭제 */
@Test
@DisplayName("삭제 성공")
void success_modify_delete(){
Post fixture = PostFixture.get();
User user = UserFixture.get("chordpli", "1234");
when(postRepository.findById(1)).thenReturn(Optional.of(fixture));
when(userRepository.findByUserName("chordpli")).thenReturn(Optional.of(user));
assertEquals(fixture.getUser().getUserName(), user.getUserName());
Assertions.assertDoesNotThrow(() -> postService.deletePost(fixture.getId(), user.getUserName()));
}
}
- 저장된 Post와 User의 값을 불러옵니다.
- postRepository의 findById를 했을 때 fixture의 값을 반환받습니다.
- userRepository의 fidByUserName을 했을때 user의 값을 반환받습니다.
- fixture의 userName과 user의 userName이 동일한지 확인합니다.
- postService의 deletePost가 예외 없이 종료된다면 성공합니다.
삭제 실패 - 유저가 존재하지 않을 때
class PostServiceTest {
...
/* 포스트 삭제 */
@Test
@DisplayName("삭제 실패_유저가 존재하지 않음")
void fail_delete_post_not_exist_user() {
Post fixture = PostFixture.get();
when(userRepository.findByUserName(any())).thenReturn(Optional.empty());
SNSAppException exception
= Assertions.assertThrows(SNSAppException.class,
() -> postService.deletePost(fixture.getId(), fixture.getUser().getUserName()));
Assertions.assertEquals(ErrorCode.USERNAME_NOT_FOUND, exception.getErrorCode());
}
}
- 저장된 post의 값을 불러옵니다.
- userRepository의 findByUserName을 했을 때 empty를 반환받습니다.
- user가 empty임으로 예외를 발생시킵니다.
- exception의 error코드가 USERNAME_NOT_FOUND인지 확인합니다.
삭제 실패 - 포스트가 존재하지 않을 때
class PostServiceTest {
...
/* 포스트 삭제 */
@Test
@DisplayName("삭제 실패_포스트 존재하지 않음")
void fail_delete_post_not_exist_post() {
Post fixture = PostFixture.get();
when(userRepository.findByUserName(any())).thenReturn(Optional.of(UserFixture.get("chordpli", "1234")));
when(postRepository.findById(fixture.getId())).thenReturn(Optional.empty());
SNSAppException exception
= Assertions.assertThrows(SNSAppException.class,
() -> postService.deletePost(fixture.getId(), fixture.getUser().getUserName()));
Assertions.assertEquals(ErrorCode.POST_NOT_FOUND, exception.getErrorCode());
}
}
- 저장된 Post의 값을 불러옵니다.
- userRepository의 fidByUserName을 했을때 user의 값을 반환받습니다.
- postRepository의 findById를 했을때 empty를 반환합니다.
- fixture의 userName과 user의 userName이 동일한지 확인합니다.
- postService의 deletePost가 예외 없이 종료된다면 성공합니다.
궁금증
1. any()를 넣으나, fixture.getUser.getUserName()등 임의의 값을 넣으나 이상 없이 테스트 코드는 실행되는데 두 차이점은 무엇일까.
반응형
'프로젝트 > Archive' 카테고리의 다른 글
[05] 리팩토링 - 2 (0) | 2022.12.29 |
---|---|
[05] 리팩토링 - 1 (0) | 2022.12.29 |
[04] Post Test 코드 작성 - 1 (Controller Test) (0) | 2022.12.27 |
[04] User Test 코드 작성 (0) | 2022.12.26 |
[JWT] JWT Exception 처리 (0) | 2022.12.25 |