DBInitializer

허준기·2024년 3월 9일
0

BCSD

목록 보기
3/8
post-custom-banner

동아리에서 springboot로 마이그레이션을 진행하면서 중요한 점 중 하나는 기존 Spring 3에서 동작하던 기능이 마이그레이션을 했을 때 그대로 동작해야하는 점이었다.

그래서 인수테스트를 통해 기능이 이전과 같이 동작하는지 테스트를 하고 통과하면 코드를 올리는 방식으로 진행되고 있다고 했다

마이그레이션에 대해서 온보딩을 하며 테스트 과정에서 테스트마다 데이터베이스 초기화가 이루어지는 과정이 어떻게 동작하는지 코드를 보라고 해서 이 글을 작성하게 됐다

DBInitializer

테스트 코드를 보니 AcceptanceTest라는 클래스가 있었다. 이 클래스 내부에서 DBInitializer를 사용중이었다.
이름을 보니 딱 봐도 이 클래스가 DB 초기화를 담당할 것 같아서 코드를 봤다

하나씩 뜯어보자

@TestComponent
public class DBInitializer {

    private static final int OFF = 0;
    private static final int ON = 1;
    private static final int COLUMN_INDEX = 1;

    private final List<String> tableNames = new ArrayList<>();

    @Autowired
    private DataSource dataSource;

    @PersistenceContext
    private EntityManager entityManager;

초기에 설정을 해주는 부분인것 같다
여기서 @PersistenceContext 어노테이션은 처음보는데 EntityManager를 빈으로 주입할 때 사용하는 어노테이션이라고 한다.

@PersistenceContext

@PersistenceContext를 쓰는 이유는 EntityManager를 쓸 때 여러 쓰레드가 동시에 접근하면 동시성 문제가 발생해서 쓰레드 간에는 공유해서는 안되기 때문이라고 한다.

이 어노테이션을 이용하면 스프링 컨테이너가 초기화되면서 EntityManagerProxy로 감싸고 호출 시마다 Proxy를 통해 EntityManeger를 생성해서 Thread-safe를 보장해줘서 공유가 안된다고 한다.

findDatabaseTableNames()

다음은 findDatabaseTableNames() 메서드가 나온다
메서드명을 보면 DB table들을 찾는 메서드인것 같다

private void findDatabaseTableNames() {
        try (final Statement statement = dataSource.getConnection().createStatement()) {
            ResultSet resultSet = statement.executeQuery("SHOW TABLES");
            while (resultSet.next()) {
                final String tableName = resultSet.getString(COLUMN_INDEX);
                tableNames.add(tableName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

첫번째 테이블부터 시작해서 List 에 저장해주는 메서드이다

truncate()

private void truncate() {
        setForeignKeyCheck(OFF);
        for (String tableName : tableNames) {
            entityManager.createNativeQuery(String.format("TRUNCATE TABLE %s", tableName)).executeUpdate();
        }
        setForeignKeyCheck(ON);
    }

메서드명 그대로 findDatabaseTableNames() 메서드에서 저장한 테이블들을 차례대로 돌면서 truncate 하는 메서드이다

이걸로 테이블 초기화를 해주는 것을 볼 수 있다

setForeignKeyCheck()

private void setForeignKeyCheck(int mode) {
        entityManager.createNativeQuery(String.format("SET FOREIGN_KEY_CHECKS = %d", mode)).executeUpdate();
    }

이건 FK 검사를 활성화하거나 비활성화하는 메서드이다
테이블을 초기화할때 FK가 설정되어 있으면 초기화가 안될수도 있어서 넣어놓은 메서드 같다

clear()

	@Transactional
    public void clear() {
        if (tableNames.isEmpty()) {
            findDatabaseTableNames();
        }
        entityManager.clear();
        truncate();
    }

마지막으로 위에 써놓은 메서드들을 전부 실행시켜 초기화 시키는 clear() 메서드이다

정리

지금까지 우리 동아리에서 사용하는 테스트 코드를 실행할 때 DB를 초기화 시키는 코드를 봤다

이 초기화하는 메서드는 모든 테스트를 실행시키기 전에 한번씩 실행이 되므로 이전에 테스트 했던 데이터들이 남아 있는 일이 없도록 해준다

profile
나는 허준기
post-custom-banner

0개의 댓글