Spring Boot: 테스트 코드 작성법

2025. 1. 5. 00:16·Springboot

오늘은 최근 진행했던 프로젝트에서 테스트 코드를 작성한 방식과 그 결과에 대해 얘기하고자 한다. 참고로 당시 테스트 커버리지 수치가 아래와 같이 꽤 좋은 결과를 보였었다.

statement coverage 기준: 88% branch coverage: 54.8% class coverage: 100% method coverage: 96.7%

 

특히 Class에서는 100%, Method에서는 96% 등을 보이며 상당히 괜찮은 결과를 보였었다. 

깃주소는 아래 참고

https://github.com/Curate-Me/claco-client

 

GitHub - Curate-Me/claco-client: 큐시즘 밋업데이 E조 큘미 Claco Client

큐시즘 밋업데이 E조 큘미 Claco Client. Contribute to Curate-Me/claco-client development by creating an account on GitHub.

github.com


일단 Spring의 계층 구조 부터 살펴보면 아래와 같다. 

 

  • Controller: 클라이언트 요청을 처리하고 서비스 계층과 통신하여 응답을 반환.
  • Service: 비즈니스 로직을 처리하고 컨트롤러와 저장소 간의 중간 다리 역할.
  • Repository: 데이터베이스와 직접 상호작용하며 데이터를 CRUD 처리.
  • Domain: 비즈니스 데이터를 표현하는 객체로, 핵심 로직과 상태를 포함.

여기서 중요한 것은 우리가 테스트 코드를 짜는 것이 아니라, 애플리케이션을 직접 실행해서 테스트를 돌린다면 만일 오류가 발생하게되면 다음 총 4개의 계층에서 어떤 계층에서 문제가 생긴 것인지 알기가 매우 힘들다. 때문에 각 계층별로 테스트 코드를 작성해서 진행한다면 오류가 발생했을때 어디서 문제가 발생했는지 금방 쉽게 알 수 있다.

 

아무튼 이번 프로젝트에서는 총 두가지 레이어에서 테스트 코드를 작성하였다.


Service Layer: 단위 테스트

단위 테스트 (Unit Test)

  • 목적: 개별 클래스 또는 메서드 단위의 동작을 테스트.
  • 범위: 특정 클래스(주로 서비스, 레포지토리 등)만 독립적으로 테스트.
  • 환경: Spring Context를 로드하지 않거나 최소한으로 로드.
  • 속도: 빠름 (비용이 적음).
  • 주요 도구:
    • @MockBean, Mockito 등을 활용해 의존성을 모킹(Mock).
    • @WebMvcTest (Controller 테스트용).
    • @DataJpaTest (Repository 테스트용).
  • 코드 예시:
@Slf4j
@ExtendWith(MockitoExtension.class)
class ClacoBookServiceTest {

	@Mock
	private MemberRepository memberRepository;
	@Mock
	private ClacoBookRepository clacoBookRepository;
	@Mock
	private SecurityContextUtil securityContextUtil;
	@InjectMocks
	private ClacoBookServiceImpl clacoBookService;

	private final Long testId = 1L;
	private final String testString = "test";

	@Test
	@DisplayName("ClacoBook 생성")
	void createClacoBook() {
		// Given
		String bookColor = "#8F9AF8";
		JwtMemberDetail jwtMemberDetailMock = mock(JwtMemberDetail.class);
		Member testMember = Member.builder()
			.id(testId)
			.email("test@test.com")
			.nickname("test")
			.role(Role.MEMBER)
			.socialId(testId)
			.build();

		when(securityContextUtil.getContextMemberInfo()).thenReturn(jwtMemberDetailMock);
		when(jwtMemberDetailMock.getMemberId()).thenReturn(testId);
		when(memberRepository.findMemberByIdWithClacoBook(testId)).thenReturn(Optional.of(testMember));
		when(clacoBookRepository.save(any(ClacoBook.class))).then(AdditionalAnswers.returnsFirstArg());
		UpdateClacoBookRequest request = UpdateClacoBookRequest.builder()
			.color(bookColor)
			.build();
		// When
		ClacoBookResponse result = clacoBookService.createClacoBook(request);

		// Then
		verify(securityContextUtil).getContextMemberInfo();
		verify(jwtMemberDetailMock).getMemberId();
		verify(memberRepository).findMemberByIdWithClacoBook(testId);

		String bookTitle = "test님의 이야기";

		assertThat(result.getId()).isNull();
		assertThat(result.getTitle()).isEqualTo(bookTitle);
		assertThat(result.getColor()).isEqualTo(bookColor);

	}

 

위 코드는 ClacoBookServiceTest라는 테스트 클래스에서 createClacoBook 메서드를 단위 테스트(Unit Test)하는 코드이다.

테스트는 Mockito를 활용하여 의존성을 모킹(Mock)하고, 테스트 대상인 ClacoBookServiceImpl의 createClacoBook 메서드가 올바르게 동작하는지 검증하는 과정이다.

 

 


 

Repository: 통합 테스트

통합 테스트 (Integration Test)

  • 목적: 여러 계층(Controller, Service, Repository 등)이 조화를 이루며 동작하는지 확인.
  • 범위: 애플리케이션의 전반적인 흐름과 의존성 검증.
  • 환경: Spring Context를 로드하고 실제 Bean을 사용.
  • 속도: 상대적으로 느림 (비용이 높음).
  • 주요 도구:
    • @SpringBootTest: 전체 애플리케이션 컨텍스트 로드.
    • TestRestTemplate, MockMvc: HTTP 요청 시뮬레이션.
    • 내장 데이터베이스(H2 등)로 실제 데이터 흐름 검증.
@Slf4j
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class ClacoBookRepositoryTest {

	@Autowired
	EntityManager entityManager;
	@Autowired
	ClacoBookRepository clacoBookRepository;

	@Test
	void findClacoBookById() {
		// Given
		String testString = "test";

		Member testMember = Member.builder()
			.email("test@test.com")
			.role(Role.MEMBER)
			.socialId(1L)
			.build();

		entityManager.persist(testMember);

		ClacoBook testBook = ClacoBook.builder()
			.title(testString)
			.color(testString)
			.member(testMember)
			.build();

		entityManager.persist(testBook);

		Long testId = testBook.getId();

		// When
		Optional<ClacoBook> result = clacoBookRepository.findClacoBookById(testId);

		// Then
		assertThat(result.isPresent()).isTrue();
		assertThat(result.get().getMember()).isEqualTo(testMember);
		assertThat(result.get().getTitle()).isEqualTo(testString);

	}
}

 

위 코드는 JPA를 활용한 ClacoBookRepository의 findClacoBookById 메서드를 테스트하는 통합 테스트 코드이다.

@DataJpaTest 애너테이션을 사용하여 JPA와 관련된 컴포넌트만 로드하며, 테스트 데이터베이스를 사용하는 환경에서 동작하도록 설정하였다. 

 


결론적으로 단위 테스트에서는 Mock 의존성 주입을 통해 동작 과정을 검증하는 거이고, 통합테스트에서는 @AutoWired를 통해 데이터베이스와 실제로 상호작용하며, 엔터티를 저장하고 조회하는 작업을 테스트하는 과정이다. 

 

좀 더 자세히 표를 통해 비교해보면 아래와 같다.

구분 단위테스트 통합테스트
목적 개별 컴포넌트 동작 검증 전체 계층의 통합 동작 검증
범위 클래스 또는 메서드 단위 여러 계층 및 의존성 포함
Spring Context 주로 로드하지 않음 전체 또는 일부 컨텍스트 로드
속도 빠름 느림
사용 사례 비즈니스 로직, 메서드 테스트 API 엔드포인트, 데이터 흐름 테스트
도구 Mockito, @MockBean @SpringBootTest, MockMvc

 

'Springboot' 카테고리의 다른 글

Spring Web MVC의 Dispatcher Servlet 파헤치기  (0) 2025.04.05
SpringBoot: TDD(Test-Driven-Development)란?  (5) 2025.01.03
Spring Batch 활용  (1) 2024.12.09
Spring boot: DDD(Domain Driven Design)란?  (0) 2024.09.23
Spring boot 쿼리 최적화 문제와 Spring Cloud Openfeign  (2) 2024.06.19
'Springboot' 카테고리의 다른 글
  • Spring Web MVC의 Dispatcher Servlet 파헤치기
  • SpringBoot: TDD(Test-Driven-Development)란?
  • Spring Batch 활용
  • Spring boot: DDD(Domain Driven Design)란?
무엇을해야하는지
무엇을해야하는지
어차피 잘될거지만, 그래도 꾸준히 열심히 최선을 다해서
  • 무엇을해야하는지
    What2Do
    무엇을해야하는지
  • 전체
    오늘
    어제
    • 분류 전체보기 (92)
      • MLOps (5)
        • DeepLearning(연구-논문) (0)
        • MS Azure AI (1)
        • MLOps projects (4)
      • DevOps&Cloud (23)
      • AWS (21)
      • Algorithm(Python) (25)
      • Springboot (8)
      • IT 시사 (2)
      • 운영체제 (4)
      • 네트워크 (2)
      • JAVA (1)
      • 면접&코테 후기 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    카엔프
    rockstat
    BFS
    testcode #spring #단위테스트 #통합테스트
    EC2
    tdd #테스트코드 #spring #springboot
    스프링부트
    leetcode #codesignal #코테 #그리디 #알고리즘
    프로세스
    knapsack #가방 #백준 #dp #topdown
    clpud
    cors #클라이언트 #서버 #서버사이드 렌더링
    ec2 #instace
    3차원
    백준
    SpringBoot
    AWS
    dp #dfs
    dp #동적계획법 #백준 #파이썬
    aws #iam #group #role
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
무엇을해야하는지
Spring Boot: 테스트 코드 작성법
상단으로

티스토리툴바