如何基于 Spring testing framework + DBUnit
简单实现一个自动化测试工具?
@Test @DataSets (setUpDataSet = "setUp.xls" , expectDataSet = "expect.xls" )public void test () {}
测试方法执行前,先loadsetUp.xls
中数据到测试库,测试方法结束后,自动和expect.xls
中数据做比对;excel里面保存的是表的数据,多个表以多个sheet页形式体现,sheet name
即是table name
;其实github上已经有个功能非常完善的工具Spring Test DBUnit ,这里只是说下大体实现思路
定义注解 @Retention (RetentionPolicy.RUNTIME)@Target (ElementType.METHOD)public @interface DataSets { String setUpDataSet () default "" ; String expectDataSet () default "" ; }
初始化XlsFileLoader和DataSourceDatabaseTester dbunit-2.4.8
中已经有现成的org.dbunit.util.fileloader.XlsDataFileLoader
,蛋疼的是它是从getClass().getResource(filename)
加载,建议重写一个,从ClassPathResource(filename).getURL()
加载
一般项目构建都会配置dataSource
,所以用DataSourceDatabaseTester
再合适不过,它来管理测试过程中数据库连接的创建销毁,以及最最重要的,根据具体DatabaseOperation
处理数据集;有个地方要注意一下,连接属性最好设置一下数据库类型,方式是实现IOperationListener
接口中connectionRetrieved()
加入下面代码,这个方法会在每次new或retrieved一个连接后立即调用connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory())
配置bean@Configuration @ImportResource ("classpath:/application-root-bean.xml" )@Profile ("test" )public class ServiceTestConfig { @Autowired DataSource dataSource; @Bean (name="databaseTester" ) public DataSourceDatabaseTester dataSourceDatabaseTester () throws Exception { DataSourceDatabaseTester databaseTester = new DataSourceDatabaseTester(dataSource()); databaseTester.setOperationListener(new CustOperationListener()); return databaseTester; } @Bean (name="xlsDataFileLoader" ) public CustomXlsFileLoader xlsDataFileLoader () { return new CustomXlsFileLoader(); } }
实现TestExecutionListener
首先prepareTestInstance()
中DI
接着beforeTestMethod()
中加载setUpDataSet
最后afterTestMethod()
中比对expectDataSet
public class ServiceTestExecutionListener implements TestExecutionListener { private IDatabaseTester databaseTester; private CustomXlsFileLoader xlsFileLoader; private IDataSet expectDataSet; public void prepareTestInstance (TestContext testCtx) throws Exception { databaseTester = (IDatabaseTester) testCtx.getApplicationContext().getBean("databaseTester" ); xlsFileLoader = (CustomXlsFileLoader) testCtx.getApplicationContext().getBean("xlsDataFileLoader" ); } public void beforeTestMethod (TestContext testCtx) throws Exception { DataSets dataSetAnnotation = testCtx.getTestMethod().getAnnotation(DataSets.class); if ( dataSetAnnotation == null ) { return ; } String dataSetName = dataSetAnnotation.setUpDataSet(); if ( ! "" .equals(dataSetName) ) { IDataSet dataSet = xlsFileLoader.load(dataSetName); databaseTester.setDataSet(dataSet); databaseTester.onSetup(); } String expectDataName = dataSetAnnotation.expectDataSet(); if ( ! "" .equals(expectDataName)) { expectDataSet = xlsFileLoader.load(expectDataName); } } public void afterTestMethod (TestContext testCtx) throws Exception { try { if ( null != expectDataSet && null != databaseTester) { IDatabaseConnection connection = databaseTester.getConnection(); connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory()); IDataSet actualDataSet = connection.createDataSet(); Assert.assertNotNull(actualDataSet); for (String tableName : expectDataSet.getTableNames()) { ITable filteredTable = DefaultColumnFilter.includedColumnsTable(actualDataSet.getTable(tableName), expectDataSet.getTableMetaData(tableName).getColumns()); Assertion.assertEquals(expectDataSet.getTable(tableName), filteredTable); } } } catch (Exception e) { throw e; } finally { if (databaseTester != null ) { databaseTester.onTearDown(); } } } public void beforeTestClass (TestContext testCtx) throws Exception {} public void afterTestClass (TestContext testCtx) throws Exception {}
配置使用 @RunWith (SpringJUnit4ClassRunner.class)@ContextConfiguration (classes = {ServiceTestConfig.class})@TestExecutionListeners ({ServiceTestExecutionListener.class})@ActiveProfiles ("test" )public abstract class AbstractServiceTest extends AbstractTransactionalJUnit4SpringContextTests {}
Reference