紀錄一下使用 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); } }
沒有留言 :
張貼留言