PostService
@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
@Transactional
public Long addPost(PostDto postDto, String userId) {
Post post = Post.builder()
.category(postDto.getCategory())
.title(postDto.getTitle())
.content(postDto.getContent())
.author(userId)
.build();
postRepository.save(post);
return post.getId();
}
public PostDto getPost(Long postId) {
Post post = findPost(postId);
return PostDto.builder()
.id(post.getId())
.category(post.getCategory())
.title(post.getTitle())
.content(post.getContent())
.author(post.getCategory())
.build();
}
@Transactional
public Long modifyPost(PostDto postDto, String userId) {
Post post = findPost(postDto.getId());
validatedUserId(post.getAuthor(), userId);
post.updatePost(postDto);
postRepository.save(post);
return post.getId();
}
@Transactional
public void deletePost(Long postId, String userId) {
Post post = findPost(postId);
validatedUserId(post.getAuthor(), userId);
postRepository.delete(post);
}
public List<PostDto> getPostList(PageRequestDto pageRequestDto) {
String category = pageRequestDto.getCategory();
Pageable pageable = pageRequestDto.getPageable(Sort.by("id"));
return postRepository.getPosts(category, pageable);
}
private void validatedUserId(String postUserId, String userId) {
if (!postUserId.equals(userId)) {
throw new BusinessExceptionHandler("권한이 없습니다.", ErrorCode.FORBIDDEN_ERROR);
}
}
private Post findPost(Long postId) {
return postRepository.findById(postId)
.orElseThrow(() -> new BusinessExceptionHandler("존재하지 않는 게시글 번호 입니다.",ErrorCode.NULL_POINT_ERROR));
}
}
Mock을 이용한 테스트를 진행
@ExtendWith(MockitoExtension.class)
class PostServiceTest {
}
단위 테스트에 공통적으로 사용할 확장 기능을 선언해주는 역할을 한다. 인자로 확장할 Extension을 명시하면된다
@ExtendWith(SpringExtension.class)
를 사용하여 Spring Test Context 프레임워크와 JUnit 5를 통합하여 테스트를 진행할 때 주로 활용됩니다. 이를 통해 Spring의 컨텍스트 관리와 관련된 기능들을 테스트 중에도 사용할 수 있습니다.
@ExtendWith(MockitoExtension.class)
를 사용하여 JUnit 5와 Mockito를 연동하여 테스트를 진행할 때 주로 활용됩니다. 이를 통해 Mockito를 활용한 모의 객체(Mock)를 생성하고 관리하면서 테스트를 수행할 수 있습니다.
...
@InjectMocks
PostService postService;
@Mock
PostRepository postRepository;
@DisplayName("게시글 등록")
@Test
void addPostTest() {
//given
String userId = "user1";
PostDto postDto = PostDto.builder()
.category("JAVA")
.title("게시글 제목")
.content("게시글 내용")
.build();
//when
//then
assertThatNoException().isThrownBy(() -> postService.addPost(postDto, userId));
}
@Nested
@DisplayName("게시글 조회")
class getPost {
@DisplayName("성공")
@Test
void success() {
//given
Post post = Post.builder()
.category("category")
.title("title")
.content("content")
.author("user1")
.build();
when(postRepository.findById(anyLong())).thenReturn(Optional.of(post));
//when
PostDto findPostDto = postService.getPost(1L);
//then
assertThat(findPostDto.getId()).isEqualTo(post.getId());
assertThat(findPostDto.getContent()).isEqualTo(post.getContent());
}
@DisplayName("실패")
@Test
void fail() {
//given
//when
//then
assertThatThrownBy(() -> postService.getPost(1L)).isExactlyInstanceOf(BusinessExceptionHandler.class);
}
}
Mockito에서 사용되며, 해당 테스트 클래스 내에서 Mock객체들을 주입 받아 필드를 초기화 하는 역할을 합니다.
모의 객체를 생성하는데 사용됩니다.
위의 코드에서는 postService가 postRepository 모의 객체를 주입받은 상태가 되고,
postServic에서 postRepository를 호출하게 되면 Mock 객체로 대체 되어 동작을 수행하게 된다.
1.Post 객체를 생성
2. when 메서드를 사용하여 postRepository.findById(anyLong()) 메서드가 호출될 때 어떤 동작을 정의. anyLong()은 어떤 Long 타입 파라미터 값이든지 매치하겠다는 것을 의미
3. thenReturn 메서드를 사용하여 findById 메서드가 호출되면 이전에 생성한 Post 객체를 반환하도록 설정합니다. 이는 가짜 Repository 호출 시 반환할 값입니다.
한마디로 postService에서 findById 메서드가 호출 될 때 내가 만든 post객체가 리턴 되는것을 의미