테스트 구조 및 전략 - KimGyuBek/Threadly GitHub Wiki
Thradly 프로젝트의 테스트는 실제 인프라 환경을 통합하여 Mocking을 최소화한 구조로 설계되었다.
모든 테스트는 JUnit 5, Spring Boot Test 기반으로 단위 -> 통합 -> 시나리오 계층으로 구성된다.
- 단위 테스트: 순수 도메인 로직 유틸 검증
- 통합 테스트: 레파지토리, Redis, Kafka 등 실제 인프라 연동한 통합 테스트
- API 시나리오 통합 테스트: 실제 요청 단위의 시나리오 기반 통합 테스트
JUnit 5, Mockito, AssertJ
test
app-api 모듈의 테스트는 단순히 컨트롤러 한두 개를 호출해 보는 수준이 아니라,
다양한 시나리오에서
- 실제 요청 및 응답 흐름
- 인증 / 인가 필터
- 예외 처리
- 전역 응답 포맷
- 도메인 서비스 + 어댑터 흐름
까지 한 번에 검증하는 실질적인 E2E 성경의 테스트를 목표로 구현했다.
- 실제 API 요청이 서비스 로직과 DB를 거쳐 정상적으로 동작하는지 검증
- JPA 매핑, 트랜잭션 경계, 인증 인가 등을 실제 환경 수준의 동작 확인
-
Post,User,Follow등 주요 도메인 전체 API 검증 - Json Fixture 로드 방식을 활용하여 시나리오별 일관된 환경에서 테스트 수행
- 높은 신뢰성: 단위 테스트로 잡기 어려운 통합 오류(JPA 매핑, 트랜잭션 등)까지 검증 가능하다.
- 유지 보수 용이: 내부 코드 변경에도 API 유지되면 테스트 수정이 불필요하다
-
높은 테스트 커버리지 확보:
Jacoco를 이용한 테스트 커버리지 측정에서app-api모듈 기준 약 89% 커버리지 달성 - 실제 시나리오 기반 검증: 실제 사용자 요청 흐름 시나리오를 기반으로 테스트를 실행한다.
// GetFollowStatsApiTest.java
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
@DisplayName("사용자 팔로워, 팔로잉 수 조회 API 테스트") // 테스트 대상 API 설명
public class GetFollowStatsApiTest extends BaseFollowApiTest {
// 팔로우 통계 테스트용 메인 사용자
public static final String MAIN_USER_ID = "main_user";
// 테스트 상수 ...
// 테스트 케이스 목록
/*
* 1. 자신에 대해서 요청 시 응답 검증
* 2. ...
* */
@Order(1)
@Nested
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@DisplayName("성공")
class success {
// 성공 케이스
/*[Case #1] 자신의 팔로워, 팔로잉 수 조회 요청 시 응답 검증*/
@Order(1) // 테스트 메서드 실행 순서
@DisplayName("1. 자신의 팔로워, 팔로잉 수 조회 요청 응답 검증") // 테스트 메서드 설명
@Test
public void getUserFollowStats_shouldSuccess_01() throws Exception {
//given
//when
//then
}
}
@Order(2)
@Nested
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@DisplayName("실패")
class fail {
// 실패 케이스
}
}특정 사용자의 팔로우 정보(팔로잉,팔로워 수)를 조회하는 API 테스트
// GetFollwStatsApiTest.java
/*[Case #1] 자신의 팔로워, 팔로잉 수 조회 요청 시 응답 검증*/
@Order(1)
@DisplayName("1. 자신의 팔로워, 팔로잉 수 조회 요청 응답 검증")
@Test
public void getUserFollowStats_shouldSuccess_01() throws Exception {
//given
// 테스트 데이터 삽입
userFollowFixtureLoader.load(
"/users/follow/follow-stats/users.json",
"/users/follow/follow-stats/follows.json"
);
String accessToken = getAccessToken(MAIN_USER_EMAIL); // 로그인 처리
//when
// userId에 해당하는 사용자의 팔로우 상태 조회 요청(테스트 할 API 요청)
CommonResponse<GetUserFollowStatsApiResponse> getUserFollowStatsResponse = sendGetUserFollowStatsRequest(
accessToken, MAIN_USER_ID, status().isOk()
);
//then
// 응답 검증
assertThat(getUserFollowStatsResponse.getData().followerCount()).isEqualTo(
EXPECTED_FOLLOWER_COUNT);
assertThat(getUserFollowStatsResponse.getData().followingCount()).isEqualTo(
EXPECTED_FOLLOWING_COUNT);
}테스트 신뢰도를 측정하기 위해서 Jacoco를 사용하여 테스트 커버리지를 측정한다.
상세 문서: Jacoco를 이용한 테스트 커버리지 측정
API 통합 테스트는 실제 DB 데이터를 직접 사용하지 않고 시나리오별로 정의된 Json Fixture 파일을 로드해서 테스트를 수행한다.
이를 통해서 일관된 테스트 환경과 높은 안정성을 유지하며, 각 테스트에서 필요한 데이터만 선택적으로 로드하여 테스트 가능
상세 문서: Fixture 기반 테스트 데이터 전략
@Nested를 이용해 성공/실패를 분리해서 하나의 테스트 클래스 안에서도 성공과 실패를 명확하게 구분할 수 있어서 가독성과 유지보수성이 향상된다.
예시

Github Actions CI 파이프라인에서 모든 테스트가 자동으로 실행하며,
PR 단계에서 바로 테스트 결과를 확인할 수 있도록 구성했다.
또한 Jacoco 테스트 커버리지는 CI 수행 후 JobSummary에 자동 출력되며, 각 모듈별 커버리지 상태를 즉시 파악할 수 있어 품질 관리가 한층 수월하다.
상세 문서: CI 파이프라인 구축