통합 테스트는 전체 애플리케이션 컨텍스트를 로드하여 실제 운영 환경과 유사한 조건에서 컴포넌트 간의 상호작용과 전체 시스템의 동작을 검증하는 데 목적이 있으며, 주로 @SpringBootTest, @AutoConfigureMockMvc과 MockMvc를 활용해 테스트한다. 반면, 단위 테스트는 특정 클래스나 메서드를 외부 의존성과 격리된 상태에서 검증하여 기능의 정확성을 빠르고 효율적으로 확인하는 데 초점을 두며, @Mock, @InjectMocks, Mockito 등을 사용해 최소한의 환경에서 테스트를 수행한다.
1️⃣ 통합 테스트
전체 Spring Boot 애플리케이션 컨텍스트(ioc)를 로드하여, 실제 환경과 유사한 조건에서 컨트롤러의 동작을 검증하는 테스트다. (DB, 서비스, 리포지토리, 시큐리티 등 모든 설정을 포함한 환경에서 테스트)
그 목적은 모듈 간 인터페이스, 데이터 흐름, 그리고 외부 시스템과의 연동이 제대로 작동하는지를 확인하는 데 있다. MockMvc를 사용해 HTTP 요청을 모의로 보내고, 그에 대한 응답을 검증합니다.
✅ 주요 어노테이션
- @SpringBootTest
- Spring Boot 애플리케이션 전체 컨텍스트를 로드해서 테스트함.
- 실제 운영 환경과 유사하게 모든 Bean을 등록하고 테스트 가능.
- @AutoConfigureMockMvc
- @SpringBootTest와 함께 사용.
- MockMvc를 자동으로 설정해줌.
- 실제 웹 서버를 띄우지 않고도 HTTP 요청을 시뮬레이션 가능.
- @Transactional
- 테스트 메서드 실행 후 DB 롤백을 자동으로 처리함.
- 테스트 간 데이터 영향 방지에 유용.
- @TestConfiguration
- 테스트 전용 Bean을 설정할 때 사용.
- 운영 환경과는 다른 테스트용 설정이 필요할 때 활용.
- @ActiveProfiles("test")
- 테스트 실행 시 사용할 프로파일 지정.
- 예: application-test.yml을 로드하고 싶을 때 → 운영에서는 실제 DB, 보안 설정, API 키 등을 사용하지만 테스트에서는 가짜 DB, 간단한 보안 설정, mock 서버 등을 쓰고 싶을 때 사용한다.
👉 사용 예시
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class MemberControllerTest {
@Autowired
private MockMvc mockMvc; ⭐️
@Autowired
private ObjectMapper objectMapper; ⭐️
@Autowired
private JdbcMemberRepository jdbcMemberRepository;
private final String email = "test@example.com";
private final String password = "123456";
private final String nickname = "tester";
@BeforeEach
void setUp() {
jdbcMemberRepository.save(new Member(email, password, nickname));
}
@Test
void signInSuccessTest() throws Exception {
SignInRequestDTO request = new SignInRequestDTO(email, password);
mockMvc.perform(post("/auth") // MockMvc를 사용해서 가짜 HTTP 요청을 보냄.
.contentType(MediaType.APPLICATION_JSON) // JSON 데이터를 보내는 요청임을 서버에 알림
.content(objectMapper.writeValueAsString(request))) // 실제 HTTP 요청의 본문(body)을 설정하는 메서드
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value("SU")) // JSON에서 code 키를 가리키는 JSONPath 표현식
.andExpect(jsonPath("$.user_id").isNumber());
}
}
⭐️ MockMvc란?
MockMvc는 Spring MVC의 HTTP 요청/응답 과정을 서버를 실제로 띄우지 않고 시뮬레이션할 수 있게 도와주는 테스트 도구
즉, 실제 웹 서버 없이도 →
- 컨트롤러에 HTTP 요청을 보내고
- 응답을 받아서
- 상태 코드, JSON 값, 헤더 등을 검증할 수 있다.
⭐️ ObjectMapper란?
ObjectMapper는 Jackson이라는 JSON 라이브러리의 핵심 클래스 중 하나로, 자바 객체와 JSON 문자열 간 변환을 도와주는 도구
MockMvc를 사용할 때, HTTP 요청에 JSON 바디를 담아 전송하려면 @RequestBody와 호환되도록 자바 객체를 JSON 문자열로 변환해야 하는데, 이때 ObjectMapper가 필요하다.
2️⃣ 단위 테스트
단위 테스트는 애플리케이션의 구성 요소 중 가장 작은 단위인 하나의 클래스 또는 메서드 단위의 로직을 외부 의존성과 격리된 상태에서 검증하는 테스트다. 이 테스트는 일반적으로 Service, 도메인 로직, 유틸리티 클래스 등에 대해 수행되며, 외부 시스템(DB, 웹 요청 등)과의 연동 없이 빠르고 정확하게 비즈니스 로직의 동작을 검증하는 것이 목적이다.
✅ 주요 어노테이션
- @Mock
- 가짜(Mock) 객체 생성
- 테스트 대상의 의존 객체를 모킹할 때
- 원하는 동작을 하도록 설정할 수 있는 테스트용 가짜 객체
- @InjectMocks: Mock 객체를 주입받는 실제 테스트 대상
- @ExtendWith(MockitoExtension.class): JUnit 5(Jupiter) 기반 테스트에서 Mockito 기능(@Mock, @InjectMocks 등)을 활성화
👉 사용 예시
@ExtendWith(MockitoExtension.class)
class MemberServiceTest {
private final int userId = 1;
private final String rawEmail = "test@email.com";
private final String rawPassword = "password123";
private final String rawNickname = "nickname";
private final String rawImage = "profile.jpg";
private final String savedPassword = "password123";
@Mock
private JdbcMemberRepository jdbcMemberRepository;
@InjectMocks
private MemberService memberService;
@Test
@DisplayName("회원가입 실패 - 중복 이메일")
void registerMember_shouldReturnDuplicateEmail_whenEmailExists() {
// given
SignUpRequestDTO request = new SignUpRequestDTO(rawEmail, rawPassword, rawNickname, null);
when(jdbcMemberRepository.findByEmail(request.getEmail()))
.thenReturn(Optional.of(new Member(rawEmail, rawPassword, rawNickname)));
// DB를 조회하지 않고, 직접 만든 Member 객체가 리턴되게 Mock하는 코드
// when
ResponseEntity<?> response = memberService.registerMember(request);
ApiResponse body = (ApiResponse) response.getBody();
// then
assertEquals(ResponseCode.DUPLICATE_EMAIL, body.getCode());
verify(jdbcMemberRepository, never()).save(any());
// 실제 저장이 일어나지 않았는지 확인
}
}
3️⃣ 공통 주요 어노테이션
- @Test: 테스트 메서드를 나타냄
- @DisplayName: 테스트 이름을 보기 좋게 지정 (테스트 리포트 가독성 향상)
- @BeforeEach, @AfterEach, @BeforeAll, @AfterAll: 테스트 클래스의 라이프 사이클을 관리하는 어노테이션
- @Nested: 내부 테스트 클래스를 계층적으로 표현 (테스트 그룹화)
- @ParameterizedTest: 매개변수를 바꿔가며 반복 테스트
- @ValueSource, @CsvSource: @ParameterizedTest와 함께 사용하여 다양한 인자 주입
끝.
'Study > SpringBoot' 카테고리의 다른 글
| Spring MVC와 Spring Security의 예외 처리 차이점 (0) | 2025.05.05 |
|---|---|
| JPA의 flush()는 언제, 왜 호출될까? (0) | 2025.04.12 |
| SpringBoot + JPA: N+1 문제 발생 원인과 해결 방법 (0) | 2025.03.22 |
| Spring Been 객체와 프록시 패턴 (0) | 2025.03.10 |
| Spring Boot 주요 모듈 및 MVC 아키텍처 (1) | 2025.03.06 |