-
Notifications
You must be signed in to change notification settings - Fork 0
DB Unit
-
DB Unit이란?
Dao혹은Repository를 테스트를 편하게 하기 위한 테스트 프레임워크이다. -
DB Unit을 적용했을 때의 장점
Dao와Repository를 테스트 할 때 코드가 깔끔해진는 장점이 있다.데이터에 직접 접근하는 객체는 DB에 직접 접근해서 테스트를 수행하기 때문에 DB에 의존적으로 테스트를 수행할 수 밖에 없다. 예를 들어, 어떤 엔티티 간의 관계가 1 대 다 관계에 있고, 다에 해당하는 엔티티를 조회하는 테스트를 수행하기 위해서는 1에 해당하는 엔티티를 먼저 생성한 이후에 다에 해당하는 엔티티를 생성하고 이를 잘 조회하는 지 테스트를 한 테스트에서 수행해야 한다.DB Unit Framework를 활용하게 되면 DB의 상태에 의존하지 않는 개발을 수행할 수 있기 때문에DB Unit을 적용하였다. -
DB Unit을 프로젝트에 적용하기
build.gradle
...
dependencies {
...
testImplementation 'org.dbunit:dbunit:2.6.0'
testImplementation 'com.github.springtestdbunit:spring-test-dbunit:1.3.0'
...
}
...DB Unit에 관한 의존성을 추가하기 위해 DBUnit Framework 의존성을 build.gradle 파일에 추가해준다.
src/test/resources/member.xml
<dataset>
<member member_id="1" alias = "alias1" password = "Password123!" name = "이름" email = "email@email.com" phone = "010-1111-2222" created_date_time = "2021-07-18 17:48:22.000000" last_modified_date_time = "2021-07-18 17:48:22.000000" deleted = "false"/>
<member member_id="2" alias = "alias2" password = "Password123!" name = "이름" email = "email@email.com" phone = "010-1111-2222" created_date_time = "2021-07-18 17:48:22.000000" last_modified_date_time = "2021-07-18 17:48:22.000000" deleted = "false"/>
</dataset>src/test/resources/board.xml
<dataset>
<member member_id="1" alias = "alias1" password = "Password123!" name = "이름" email = "email@email.com" phone = "010-1111-2222" created_date_time = "2021-07-18 17:48:22.000000" last_modified_date_time = "2021-07-18 17:48:22.000000" deleted = "false"/>
<member member_id="2" alias = "alias2" password = "Password123!" name = "이름" email = "email@email.com" phone = "010-1111-2222" created_date_time = "2021-07-18 17:48:22.000000" last_modified_date_time = "2021-07-18 17:48:22.000000" deleted = "false"/>
<board board_id = "1" title="title" content="content" created_date_time="2021-07-18 17:48:22.000000" last_modified_date_time="2021-07-18 17:48:22.000000" deleted="false" member_id="1"/>
<board board_id = "2" title="title" content="content" created_date_time="2021-07-18 17:48:22.000000" last_modified_date_time="2021-07-18 17:48:22.000000" deleted="false" member_id="2"/>
<board board_id = "3" title="title" content="content" created_date_time="2021-07-18 17:48:22.000000" last_modified_date_time="2021-07-18 17:48:22.000000" deleted="false" member_id="1"/>
<board board_id = "4" title="title" content="content" created_date_time="2021-07-18 17:48:22.000000" last_modified_date_time="2021-07-18 17:48:22.000000" deleted="false" member_id="2"/>
</dataset>테스트 할 Entity의 정보를 XML 파일로 작성한다. 이를 위해서는 test 경로 하위에 resources 경로를 만들고 그 아래에 원하는 이름으로 XML 파일을 생성한다. 그 다음에는 다음과 같이 엔티티의 정보가 담긴 XML 파일을 만든다. 주의해야 할 점은 엔티티의 속성 중에서 not null 속성을 가진 관한 정보를 넣어주지 않거나 unique 속성을 동일하게 가져갈 경우 DatabaseUnitException 이 발생한다. insert 문으로 직접 넣어주기 때문에 auto increament도 적용된다.
DBUnitTestConfiguration.java
import com.github.springtestdbunit.bean.DatabaseConfigBean;
import com.github.springtestdbunit.bean.DatabaseDataSourceConnectionFactoryBean;
import org.dbunit.ext.h2.H2DataTypeFactory;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
@TestConfiguration
public class DBUnitTestConfiguration {
@Bean
public DatabaseConfigBean dbUnitDatabaseConfig() {
DatabaseConfigBean databaseConfigBean = new DatabaseConfigBean();
databaseConfigBean.setAllowEmptyFields(true);
databaseConfigBean.setDatatypeFactory(new H2DataTypeFactory());
return databaseConfigBean;
}
@Bean
public DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection(final DataSource dataSource) {
DatabaseDataSourceConnectionFactoryBean dbUnitDatabaseConnection = new DatabaseDataSourceConnectionFactoryBean();
dbUnitDatabaseConnection.setDataSource(dataSource);
dbUnitDatabaseConnection.setDatabaseConfig(dbUnitDatabaseConfig());
return dbUnitDatabaseConnection;
}
}test 하위 폴더에 DB Unit을 활용하기 위한 DatabaseConfigBean과 DatabaseDataSourceConnectionFactoryBean 두 가지 Bean을 등록해준다. 먼저 DatabaseConfigBean에서는 빈 컬럼을 허용하는 부분과 Database의 타입을 지정해준다. DatabaseDataSourceConnectionFactoryBean 에는 dataSource와 dbUnitDatabaseConfig 빈을 설정하여 등록해 준다.
MemberRepositoryTest.java
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseOperation;
import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.DatabaseTearDown;
import com.github.springtestdbunit.annotation.DbUnitConfiguration;
import com.project.kodesalon.config.DBUnitTestConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
@DataJpaTest
@Import(DBUnitTestConfiguration.class)
@DbUnitConfiguration(databaseConnection = "dbUnitDatabaseConnection")
@DatabaseSetup(value = "classpath:member.xml", type = DatabaseOperation.CLEAN_INSERT)
@DatabaseTearDown(value = "classpath:member.xml", type = DatabaseOperation.DELETE_ALL)
@TestExecutionListeners({DbUnitTestExecutionListener.class, DependencyInjectionTestExecutionListener.class})
public class MemberRepositoryTest {
@Autowired
private MemberRepository memberRepository;
...
//Test code
}먼저 애노테이션 하나 하나 살펴보도록하면, @DataJpaTest 는 해당 Repository를 테스트 하기 위한 Entity와 Repository만 띄울 때 사용하는 애노테이션이다. 다음으로는 @Import 를 활용해서 이전에 등록해두었던 빈들을 활용하기 위한 Configuration 클래스를 import한다. 다음으로는 DB Connection에 관한 빈을 @DbunitConfiguration 애노테이션을 활용하여 이전에 등록해 두었던 dbUnitDatabaseConnection 빈을 등록해준다. 다음으로는 테스트가 수행될때 마다 DB에 저장되고 삭제되야 할 Data Set과 DB 연산의 타입을 지정해주는 애노테이션인 @DatabaseSetUp , @DatabaseTearDown 을 통해 지정해준다. DatabaseOperation 의 종류는 아래에 별도로 정리해 두고, @TestExcecutionListeners 는 Test가 수행되기 전, 후에 수행되어야 할 것을 Custom한 클래스로 사용하기 위한 애노테이션인데, 테스트가 수행되기 전 후로 DB에 저장하고 삭제하는 연산이 반드시 필요하기 때문에 두 클래스를 설정해서 지정해준다.
DatabaseOperation
- UPDATE : 존재하는 데이터베이스에서 DataSet을 수정한다.
- INSERT : 기존 데이터베이스 테이블에서 DataSet을 추가한다.
- REFRESH : 기존에 없는 데이터는 추가하고, 존재하는 데이터는 값을 변경한다.
- DELETE : DataSet과 맞는 데이터들만 삭제한다.
- DELETE_ALL : 전체 데이터를 삭제한다.
- TRUNCATE_TABLE : 데이터 셋에 정의된 모든 테이블의 컬럼을 삭제한다.
- CLEAN_INSERT : 모든 컬럼을 삭제한 후 Insert 한다.
위와 같이 지정해 주면 각각의 테스트가 수행될때 마다 XML 파일로 정리해 둔 데이터 셋을 바탕으로 테스트를 수행할 수 있고, 테스트 간에 데이터가 변경되거나 삭제될 경우 테스트가 깨지는 문제를 방지할 수 있어서 데이터베이스 상태에 의존적인 테스트를 줄일 수 있다.
스프링부트에서 DbUnit 을 이용하여 DB 테스트 해보기 | 우아한형제들 기술블로그
Spring boot에서 DBUnit 사용하기