Test
[Test] 서비스 계층 테스트
감자b
2024. 12. 30. 00:20
서비스 계층의 경우 주로 비즈니스 로직이 구현되고 데이터 가공이 빈번하게 이루어지는 계층이므로 데이터의 정합성과 예외 케이스를 신경써서 테스트를 작성해야 한다.
비즈니스 로직은 주로 Repository나 외부 서비스 계층과의 잦은 데이터 교환이 이루어지는 경우가 많기 때문에 무조건적인 단위 테스트 방식이 아니라 통합 테스트와 적절히 섞어서 많이 작성된다고 한다.
아래와 같은 서비스 로직이 있다고 하자.
@Service
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
public PostResponse.PostResponseDto findOne(Long id) {
Post post = postRepository.findById(id)
.orElseThrow(IllegalStateException::new);
return PostMapper.toPostResponseDto(post);
}
}
해당 서비스에 대한 테스트 코드를 작성해보도록 하겠다.
@SpringBootTest
@Transactional
class PostServiceTest {
@Autowired
private PostService postService;
@Autowired
private PostRepository postRepository;
@Test
@DisplayName("게시글 단건 조회 성공 테스트")
void 게시글_단건_조회_성공() {
// given
Post savedPost = postRepository.save(Post.builder()
.title("테스트 제목")
.content("테스트 내용")
.build());
// when
PostResponse.PostResponseDto foundPost = postService.findOne(savedPost.getId());
// then
assertThat(foundPost).isNotNull();
assertThat(foundPost.getId()).isEqualTo(savedPost.getId());
assertThat(foundPost.getTitle()).isEqualTo("테스트 제목");
assertThat(foundPost.getContent()).isEqualTo("테스트 내용");
}
@Test
@DisplayName("존재하지 않는 게시글 조회시 예외 발생 테스트")
void 게시글_단건_조회_예외() {
// given
Long nonExistentId = 999L;
// when & then
assertThrows(IllegalStateException.class,
() -> postService.findOne(nonExistentId));
}
}
@SpringBootTest
스프링 부트는 해당 애노테이션을 통해 테스트에 필요한 모든 의존성을 제공(통합 테스트)
JUnit4를 사용한다면 @RunWith(SpringRunner.class)와 같이 사용해야 한다.
@Transactional
테스트에서 사용 시 테스트 종료 후 자동으로 롤백
assertThat(foundPost).isNotNull();
assertThat(foundPost.getId()).isEqualTo(savedPost.getId());
assertThat(foundPost.getTitle()).isEqualTo("테스트 제목");
assertThat(foundPost.getContent()).isEqualTo("테스트 내용");
→ 서비스 로직을 통해 얻어온 데이터가 일치하는지 확인
추가로 외부 시스템과 연동을 담당하는 모듈의 경우 모킹하여 해당 시스템이 테스트에 영향을 미치지 않도록 하는 것이 좋다.