Skip to content

TestConfig 및 (이전) Fixture 활용 방법

나경호(Na Gyeongho) edited this page May 27, 2025 · 1 revision

TestConfig 활용 방법

기존상황

각 테스트 클래스마다 필요한 Config 파일을 하나하나 import문으로 정의하였습니다.

개선방향

TestConfig를 도입하여 테스트 환경에서 필요한 Config 클래스를 한 곳에서 관리하도록 하였습니다.

package com.evenly.took.global.config;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Import;

import com.evenly.took.global.config.testcontainers.MySQLTestConfig;
import com.evenly.took.global.config.testcontainers.RedisTestConfig;
import com.evenly.took.global.config.testcontainers.S3TestConfig;

@Import({
		FcmTestConfig.class,
		MySQLTestConfig.class,
		S3TestConfig.class,
		RedisTestConfig.class
})
@TestConfiguration
public class TestConfig {
}

TestConfig 역할

  • 테스트 환경에서 필요한 빈 정의
  • import 구문 한 곳에서 관리

TestConfig 활용방법

테스트 환경에서 Import가 필요한 Config 클래스는 위 클래스에 정의해주시면 됩니다.

위 클래스에서 import된 클래스는 IntegrationTest, ControllerTest, ServiceTest에서 적용됩니다!

Fixture 활용 방법

기존상황

제가 작성한 예시 코드입니다

제가 작성한 예시 코드입니다

  • 테스트 코드에서 필요한 데이터를 생성할 때 많은 필드로 인해 가독성이 저하됩니다 (특히 Card 엔티티의 경우 14개의 필드가 필요합니다)
  • 테스트 로직에서 사용되지 않는 데이터까지 관리해야 하는 수고로움이 있었습니다

개선방향

기존 코드를 개선한 코드입니다

기존 코드를 개선한 코드입니다

  • Fixture를 도입하여 테스트 코드(특히 given절과 @BeforeEach)의 가독성을 높였습니다.
  • Fixture 클래스를 재사용하여 데이터 생성 작업에 투입되는 리소스를 줄였습니다.
  • 테스트 로직에서 사용되는 데이터만 관리하도록 하였습니다.
    • 사용되는 데이터만 관리한다는 의미

      아래와 같은 더미데이터는 중요하지 않은 데이터입니다. 따라서 해당 데이터는 fixture 클래스로 이동시키고, 중요한 데이터만 테스트 로직에서 파라미터로 정의하도록 하였습니다.

image

Fixture 역할

엔티티 생성 및 데이터베이스에 저장

Fixture 활용예시

상황예시 : given절에서 한 장의 명함을 DB에 저장한 후 when & then절에서 해당 명함을 조회해 검증하고 싶다.

// given
Card card = cardFixture.createCard(mockUser);

// when
// 명함 상세 조회 API 요청해서 응답받기 (CardDetailResponse)

// then
// Card와 CardDetailResponse 비교하여 검증

Fixture 확장방법

아래와 같이 createCard() 메서드가 오버로딩 되어있습니다.

이 외의 방법으로 card를 생성하고 싶다면, 오버로딩을 통해 메서드를 생성한 후 사용해주면 됩니다.

public Card createCard(User user) {
		// 유저로 카드 생성하기
		return createCard(user,
			careerFixture.serverDeveloper(),
			DEFAULT_PREVIEW_INFO,
			DEFAULT_NICKNAME,
			DEFAULT_IMAGE_PATH,
			DEFAULT_INTEREST_DOMAIN,
			DEFAULT_SUMMARY,
			DEFAULT_ORGANIZATION,
			DEFAULT_SNS,
			DEFAULT_REGION,
			DEFAULT_HOBBY,
			DEFAULT_NEWS,
			DEFAULT_CONTENT,
			DEFAULT_PROJECT);
	}

	public Card createCard(User user, String nickname, PreviewInfoType previewInfoType) {
		// 유저, 닉네임, 썸네일 정보로 카드 생성하기
		return createCard(user,
			careerFixture.serverDeveloper(),
			previewInfoType,
			nickname,
			DEFAULT_IMAGE_PATH,
			DEFAULT_INTEREST_DOMAIN,
			DEFAULT_SUMMARY,
			DEFAULT_ORGANIZATION,
			DEFAULT_SNS,
			DEFAULT_REGION,
			DEFAULT_HOBBY,
			DEFAULT_NEWS,
			DEFAULT_CONTENT,
			DEFAULT_PROJECT);
	}

	public Card createCard(User user, String nickname, String organization, String region) {
		// 유저, 닉네임, 조직, 지역으로 카드 생성하기
		return createCard(user,
			careerFixture.serverDeveloper(),
			DEFAULT_PREVIEW_INFO,
			nickname,
			DEFAULT_IMAGE_PATH,
			DEFAULT_INTEREST_DOMAIN,
			DEFAULT_SUMMARY,
			organization,
			DEFAULT_SNS,
			region,
			DEFAULT_HOBBY,
			DEFAULT_NEWS,
			DEFAULT_CONTENT,
			DEFAULT_PROJECT);
	}

	public Card createCard(User user, List<SNS> sns, List<Content> contents, List<Project> projects) {
		return createCard(user,
			careerFixture.serverDeveloper(),
			DEFAULT_PREVIEW_INFO,
			DEFAULT_NICKNAME,
			DEFAULT_IMAGE_PATH,
			DEFAULT_INTEREST_DOMAIN,
			DEFAULT_SUMMARY,
			DEFAULT_ORGANIZATION,
			sns,
			DEFAULT_REGION,
			DEFAULT_HOBBY,
			DEFAULT_NEWS,
			contents,
			projects);
	}

	private Card createCard(User user,
		Career career,
		PreviewInfoType previewInfoType,
		String nickname,
		String imagePath,
		List<String> interestDomain,
		String summary,
		String organization,
		List<SNS> sns,
		String region,
		String hobby,
		String news,
		List<Content> contents,
		List<Project> projects) {

		// 전체 필드로 card를 생성하는 메서드로, fixture 내부에서 재사용을 위해 선언
		Card card = Card.builder()
			.user(user)
			.career(career)
			.previewInfo(previewInfoType)
			.nickname(nickname)
			.imagePath(imagePath)
			.interestDomain(interestDomain)
			.summary(summary)
			.organization(organization)
			.sns(sns)
			.region(region)
			.hobby(hobby)
			.news(news)
			.content(contents)
			.project(projects)
			.build();
		return cardRepository.save(card);
	}
Clone this wiki locally