테스트 분리

춤인형의 개발일지·2025년 2월 20일

이것저것

목록 보기
9/13

로컬과 테스트 분리를 왜?

TTD를 작성하다보면 local과는 관계 없이 실행할 수 있어야한다. 따라서 local과 test용으로 따로 분리를 해줘야한다.

파일 구조

  • application.properties (기본 설정 파일)
  • application-local.properties (로컬용 설정 파일)
  • application-test.properties (테스트용 설정 파일)

application.properties (기본 설정 파일)

spring.profiles.active=local

# JWT
jwt.secret=uz7MtIBd5PpX0knZuSB4RLlgFJ/v7ySsMofaMGZ1wec=
jwt.expiration-time=43200000

# JPA
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comment=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.highlight_sql=true
logging.level.org.hibernate.orm.jdbc.bind=TRACE

spring.profiles.active=local이게 꼭 들어가서 기본 설정이 local과 같다는 것을 넣어줘야한다.


application-local.properties (로컬용 설정 파일)

spring.datasource.url=jdbc:postgresql://localhost:5432/db이름
spring.datasource.username=이름
spring.datasource.password=이름
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=create

postSql을 사용할 때 db를 만드는 부분을 넣어준다.


application-test.properties (테스트용 설정 파일)
빈 파일로 만들어둔다.

테스트

테스트를 위해 @ActiveProfiles("test") 을 넣어줘야한다.

import org.springframework.test.context.ActiveProfiles;

@ActiveProfiles("test") // application-test.properties 설정 적용
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class StudentAcceptanceTest {
    // 생략
}

테스트끼리 격리

테스트끼리의 영향을 받지 않기 위한 격리도 필요하다.

test에 DataBaseCleanUP의 파일을 만들어둔다.

import jakarta.persistence.Entity;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class DatabaseCleanup implements InitializingBean {
    @PersistenceContext
    private EntityManager entityManager;
    private List<String> tableNames;
    @Override
    public void afterPropertiesSet() {
        tableNames = entityManager.getMetamodel().getEntities().stream()
                .filter(e -> e.getJavaType().getAnnotation(Entity.class) != null)
                .map(e -> e.getName()
                        .replaceAll("([a-z])([A-Z])", "$1_$2") // camel case to snake case
                        .toLowerCase())
                .collect(Collectors.toList());
    }
    @Transactional
    public void execute() {
        entityManager.flush();
        entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate();
        for (String tableName : tableNames) {
            entityManager.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate();
            entityManager.createNativeQuery("ALTER TABLE " + tableName + " ALTER COLUMN ID RESTART WITH 1").executeUpdate();
        }
        entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate();
    }
}

이 만들어둔 파일을 test할 때 주입해주면 된다.

@Autowired
    DatabaseCleanup databaseCleanup;

    @BeforeEach
    void setUp() {
        databaseCleanup.execute();
    }

이런식으로 작성해준다.

0개의 댓글