紀錄一下使用 Spring 搭配 Database Rider 的注意事項。
下面直接看範例,相關的說明也寫在注解上了。
最主要要注意的地方是,
如果不使用 Dabase Rider 的 Annotation 的話,跟之前這篇
使用 Dabase Rider 進行 Database 測試
的寫法是差不多的,只差在取得 Connection 的地方可以直接使用 Spring 幫我們裝配好的
JdbcTemplate 來取得 Datasource,再使用
DataSourceUtils.getConnection(dataSource) 取得 Connection。
如果想使用 Database Rider 的 Annotation 的話,需要使用
@DBRider(dataSourceBeanName = "test_DataSource")
這個 Annotaton 來設定 dataSourceBeanName,
@DBRider 本身就是 @ExtendWith(DBUnitExtension.class) 和 @Test 的組合,
但多提供了我們設定 dataSourceBeanName 的地方,
我們只要把設定在 Spring 中需要的 dataSourceBeanName 設定給 @DBRider,
之後 Database Rider 的 @DataSet, @ExpectedDataSet 這些 Annotation 就會直接用dataSourceBeanName 去找出 Spring 裝配好的 dataSource 進行 Database 連線,
所以不用再像這篇
使用 Dabase Rider 進行 Database 測試
一樣特別去設定 ConnectionHolder。
package test.dao;
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.dbunit.DatabaseUnitException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import com.github.database.rider.core.api.configuration.DBUnit;
import com.github.database.rider.core.api.dataset.DataSet;
import com.github.database.rider.core.api.dataset.DataSetFormat;
import com.github.database.rider.core.api.dataset.ExpectedDataSet;
import com.github.database.rider.core.api.exporter.DataSetExportConfig;
import com.github.database.rider.core.configuration.DBUnitConfig;
import com.github.database.rider.core.configuration.DataSetConfig;
import com.github.database.rider.core.configuration.ExpectedDataSetConfig;
import com.github.database.rider.core.dsl.RiderDSL;
import com.github.database.rider.core.exporter.DataSetExporter;
import com.github.database.rider.junit5.api.DBRider;
//讀取配置檔讓 Spring 處理 Bean 的依賴裝配
@SpringJUnitWebConfig(locations = {"file:WebContent/WEB-INF/mvc-config.xml"})
//如果要使用 Database Rider 的 Annotation (@Dataset, @ExpectedDataSet 等)
//才需要使用 @DBRider,
//@DBRider 內包含 @ExtendWith(DBUnitExtension.class) 和 @Test,
//並且多了一個 dataSourceBeanName 屬性,用來指定要使用的 Spring DataSourceBean 名稱
@DBRider(dataSourceBeanName = "test_DataSource")
@DBUnit(cacheConnection = false,
allowEmptyFields = true)
@TestInstance(Lifecycle.PER_CLASS)
class DBRiderTest {
//如果不使用 Database Rider 的 Annotation,
//可以自行依需要取得 JdbcTemplate,進而取得 Datasource 和 Jdbc Connection
@Autowired
@Qualifier("test_JdbcTemplate")
JdbcTemplate test_JdbcTemplate;
final String testResourceFolderPath = "";
final String backupDatasetResourcePath = "/backupDataset.xlsx";
final String testDatasetResourcePath = "/testDataset.xlsx";
final String[] includeTableList = new String[] {"test_table"};
//因為 @ExportDataSet 似乎無法使用在 @BeforeAll 及 @AfterAll 上,
//所以這裡不使用 Annotation,直接使用 API 進行 backup dataset 的 export
@BeforeAll
void exportBackupDataset() throws SQLException, DatabaseUnitException, URISyntaxException {
URL backupDatasetResourceFolderUrl = DBRiderTest.class.getClassLoader().getResource(testResourceFolderPath);
File backupDatasetResourceFolder = Paths.get(backupDatasetResourceFolderUrl.toURI()).toFile();
String backupDatasetResourceFilePath = backupDatasetResourceFolder.getAbsolutePath() + backupDatasetResourcePath.replace("/", File.separator);
DataSource dataSource = test_JdbcTemplate.getDataSource();
Connection conn = DataSourceUtils.getConnection(dataSource);
DataSetExporter.getInstance().export(conn,
new DataSetExportConfig()
.dataSetFormat(DataSetFormat.XLSX)
.includeTables(includeTableList)
.queryList(new String[] {})
.outputFileName(backupDatasetResourceFilePath));
DataSourceUtils.releaseConnection(conn, dataSource);
}
//因為 @DataSet 似乎無法使用在 @BeforeAll 及 @AfterAll 上,
//所以這裡不使用 Annotation,直接使用 API 進行 backup dataset 的 import
@AfterAll
void importBackupDataset() {
//直接利用 Spring Inject 裝配好的 JdbcTemplate,並取得 DataSource 和 Connection
DataSource dataSource = test_JdbcTemplate.getDataSource();
Connection conn = DataSourceUtils.getConnection(dataSource);
RiderDSL.withConnection(conn)
.withDataSetConfig(new DataSetConfig(testResourceFolderPath + backupDatasetResourcePath)
//依需求設定 import dataset 要執行的動作,
//例如: Sql Server (MS Sql) 要 Insert/Update 主鍵時需要 SET IDENTITY_INSERT test_table ON
.executeStatementsBefore(""))
.withDBUnitConfig(new DBUnitConfig()
.addDBUnitProperty("allowEmptyFields", true))
.createDataSet();
DataSourceUtils.releaseConnection(conn, dataSource);
//do other things
}
//使用 @DataSet 來 import test dataset
@BeforeEach
@DataSet(value = "testDataset.xlsx",
//依需求設定 import dataset 要執行的動作,
//例如: Sql Server (MS Sql) 要 Insert/Update 主鍵時需要 SET IDENTITY_INSERT test_table ON
executeStatementsBefore = {""})
void importTestDataset() {
}
@Test
void test() {
System.out.println("test");
Assertions.assertTrue(true);
}
//使用 @ExpectedDataSet Annotation 比較 database table 的資料是否和 expected dataset 一致
@Test
@ExpectedDataSet(value = "expectedDataset.xlsx")
void testExpectedDatasetByAnnotation() throws DatabaseUnitException, SQLException {
//做你想做的 Test
//例如以下是比較 Actual dataset 和 expected dataset 的範例 (請再自己準備一個 expected dataset file):
//自己修改一下 database table 的資料
test_JdbcTemplate.update("UPDATE test_table SET title = 'ABC' WHERE id = 2");
//因為使用了 @ExpectedDataSet Annotation,所以這裡就不需要再多寫用 RiderDSL 等的程式碼了
}
//也可以不使用用 @ExpectedDataSet Annotation,直接使用 RiderDSL 來比較 database table 的資料是否和 expected dataset 一致
@Test
void testExpectedDataset() throws DatabaseUnitException, SQLException {
//做你想做的 Test
//例如以下是比較 Actual dataset 和 expected dataset 的範例 (請再自己準備一個 expected dataset file):
//自己修改一下 database table 的資料
test_JdbcTemplate.update("UPDATE test_table SET title = 'ABC' WHERE id = 2");
//比較 database table 的資料是否和 expected dataset 一樣
DataSource dataSource = test_JdbcTemplate.getDataSource();
Connection conn = DataSourceUtils.getConnection(dataSource);
RiderDSL.withConnection(conn)
.withDataSetConfig(new DataSetConfig("expectedDataset.xlsx"))
.withDBUnitConfig(new DBUnitConfig()
.addDBUnitProperty("escapePattern", "\"?\"")
.addDBUnitProperty("caseSensitiveTableNames", true)
.addDBUnitProperty("allowEmptyFields", true))
.expectDataSet(new ExpectedDataSetConfig());
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
沒有留言 :
張貼留言