이전 포스팅에서 단위 테스트&JUnit와 계층별 단위테스트에 대해 다뤄보았다.
이번 포스팅에서는 통합테스트에 대해서 다뤄볼 예정이다.
[SpringBoot] 단위테스트(Unit Test)와 JUnit
🌱 단위 테스트(Unit Test)란? 단위 테스트(Unit Test)란 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트이다. 여기서 모듈은 애플리케이션에서 작동하는 하나의 기능 또는 메
caffeineoverflow.tistory.com
[SpringBoot] 계층별 단위테스트
이전 포스팅에서 테스트의 개념 및 종류와 단위 테스트&JUnit을 간략하게 다뤄보았다. 이번 포스팅에서는 스프링의 계층별 단위 테스트에 대해서 다뤄볼 예정이다. [SpringBoot] 테스트 개념과 종류
caffeineoverflow.tistory.com
🌱 통합테스트(Integration Test)란?
통합테스트(Integration Test)란 서로 다른 모듈 혹은 클래스 간 상호작용의 유효성을 검증하는 테스트이다.
일반적으로 애플리케이션은 여러 개의 모듈들로 구성되고, 모듈들끼리 상호작용을 하며 기능을 수행한다. 그렇기에 통합된 모듈들이 올바르게 연계되어 동작하는지 검증이 필요한데, 이러한 목적으로 진행되는 테스트가 통합 테스트이다.
🌱 Controller, Service, Repository 구성
테스트에 앞서 기본이 되는 코드를 살펴보자.
회원을 조회하는 클라이언트의 요청이 들어오면, Controller -> Service -> Repository의 순으로 호출이 된다고 가정해 보자.
각 각의 코드는 최소한의 기능만 동작하게 구현하였다.
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
/**
* 회원 조회
*/
@GetMapping("/members/{memberId}")
public Member findMember(@PathVariable Long memberId) {
return memberService.findMember(memberId);
}
}
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
public Member findMember(Long memberId) {
return memberRepository.findByMemberId(memberId);
}
@Transactional
public Member saveMember(Member member) {
return memberRepository.save(member);
}
}
public interface MemberRepository extends JpaRepository<Member, Long> {
Member findByMemberId(Long memberId);
}
위의 코드를 기반으로 테스트 코드를 작성해 보자.
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@Transactional
@ActiveProfiles("dev")
class IntegrationTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@Autowired
private MemberService memberService;
@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
@Test
@DisplayName("회원 조회")
void findMember() throws Exception {
// given
Member member = Member.builder()
.name("CHOI")
.build();
memberService.saveMember(member);
// when
ResultActions actions = mockMvc.perform(
get("/members/{memberId}", 1L)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
);
// then
actions.andExpect(status().isOk())
.andExpect(jsonPath("$.memberId").value(1))
.andExpect(jsonPath("$.name").value("CHOI"))
.andDo(print());
}
}
위의 테스트 코드는 회원을 조회하기 위한 테스트 코드 예시이다.
우선 given절에서는 테스트를 위한 데이터를 생성하기 위하여 memberService의 saveMember()를 사용하여 데이터를 생성한다.
이후 when절과 then절에서는 회원조회를 하는 Controller를 호출하여 정상적으로 동작하는지 검증을 진행한다.
Controller가 호출되면 Controller -> Service -> Repository 순으로 순차적인 호출이 일어나게 되고, 이는 전반적인 코드에 대해 테스트를 진행한 것으로 볼 수 있다. 이처럼 통합테스트를 진행할 경우 전체적인 테스트를 진행할 수 있어 코드 커버리지가 높아진다는 장점이 있다.
다음으로는 통합테스트에서 사용된/사용되는 어노테이션에 대해서 알아보자.
- @SpringBootTest
통합테스트에서 가장 핵심이 되는 어노테이션이다. 실제 구동되는 애플리케이션과 똑같이 ApplicationContext를 로드하기 때문에 운영환경과 가장 유사한 테스트를 진행할 수 있다. 하지만 전체 애플리케이션을 띄우기 때문에 규모가 커질수록 테스트가 느려진다는 단점이 있다. - @Transactional
클래스 내부의 각각의 테스트 메서드가 실행될 때마다, 데이터베이스를 롤백한다. 반복 가능한 테스트 코드를 위해 필요하다. 만약, 테스트 후 데이터를 직접 보고 싶다면 @Rollback(false) 어노테이션을 추가하면 된다. - @Disabled
해당 어노테이션이 지정된 테스트 클래스 또는 테스트 메서드를 실행하지 않는다. - @ActiveProfiles
테스트 수행 사용할 프로파일을 지정할 수 있다. @ActiveProfiles("dev") 어노테이션을 사용하면 dev 프로파일을 사용한다.
References.
1. 개발하는 콩 - Spring - 나의 첫 통합 테스트(Integration Test)
2. lundy - [Spring Boot] @SpringBootTest 통합 테스트와 @Transactional
3. 샤아이인 - [Spring] @SpringBootTest
'Spring' 카테고리의 다른 글
[SpringBoot] 에러 전파와 /error 호출 흐름 (1) | 2024.12.14 |
---|---|
[Spring] 어노테이션(Annotation) (0) | 2023.11.17 |
[SpringBoot] 계층별 단위테스트 (1) | 2023.10.06 |
[Spring] @Configuration (0) | 2023.10.06 |
[SpringBoot] 단위테스트(Unit Test)와 JUnit (0) | 2023.09.30 |