关于单元测试之王
第一步:pom依賴
<!-- 單元測試 --><dependency><groupId>org.unitils</groupId><artifactId>unitils-core</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-dbunit</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-io</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-database</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-spring</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.dbunit</groupId><artifactId>dbunit</artifactId><version>2.5.3</version></dependency><dependency><groupId>org.easymock</groupId><artifactId>easymock</artifactId><version>3.5.1</version><scope>test</scope></dependency><dependency><groupId>org.easymock</groupId><artifactId>easymock</artifactId><version>RELEASE</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-core</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-dbunit</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-io</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-database</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.unitils</groupId><artifactId>unitils-spring</artifactId><version>3.4.2</version></dependency><dependency><groupId>org.dbunit</groupId><artifactId>dbunit</artifactId><version>2.5.3</version></dependency>pom
第二步:編寫關于unitils的4個工具類,我現在放在unitils包下
package com.odianyun.back.order.web.unitils;import java.io.File;
import java.util.Arrays;
import java.util.Properties;import org.unitils.core.UnitilsException;
import org.unitils.dbunit.datasetfactory.DataSetFactory;
import org.unitils.dbunit.util.MultiSchemaDataSet;public class MultiSchemaXlsDataSetFactory implements DataSetFactory {protected String defaultSchemaName;public void init(Properties configuration, String s) {this.defaultSchemaName = s;}public MultiSchemaDataSet createDataSet(File... dataSetFiles) {try {MultiSchemaXlsDataSetReader xlsDataSetReader = new MultiSchemaXlsDataSetReader(defaultSchemaName);return xlsDataSetReader.readDataSetXls(dataSetFiles);} catch (Exception e) {throw new UnitilsException("創建數據集失敗:" + Arrays.toString(dataSetFiles), e);}}public String getDataSetFileExtension() {return "xls";}
} MultiSchemaXlsDataSetFactory package com.odianyun.unitils;import org.dbunit.database.AmbiguousTableNameException; import org.dbunit.dataset.DefaultDataSet; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; import org.dbunit.dataset.excel.XlsDataSet; import org.unitils.core.UnitilsException; import org.unitils.dbunit.util.MultiSchemaDataSet;import java.io.File; import java.io.FileInputStream; import java.util.*;public class MultiSchemaXlsDataSetReader {private String pattern = ".";private String defaultSchemaName;public MultiSchemaXlsDataSetReader(String defaultSchemaName) {this.defaultSchemaName = defaultSchemaName;}public MultiSchemaDataSet readDataSetXls(File... dataSetFiles) {try {Map<String, List<ITable>> tbMap = getTables(dataSetFiles);MultiSchemaDataSet dataSets = new MultiSchemaDataSet();for (Map.Entry<String, List<ITable>> entry : tbMap.entrySet()) {List<ITable> tables = entry.getValue();try {DefaultDataSet ds = new DefaultDataSet(tables.toArray(new ITable[]{}));dataSets.setDataSetForSchema(entry.getKey(), ds);} catch (AmbiguousTableNameException e) {throw new UnitilsException("構造DataSet失敗!", e);}}return dataSets;} catch (Exception e) {throw new UnitilsException("解析Excel文件出錯:", e);}}private Map<String, List<ITable>> getTables(File... dataSetFiles) {Map<String, List<ITable>> tableMap = new HashMap();// 需要根據schema把Table重新組合一下try {String schema, tableName;for (File file : dataSetFiles) {IDataSet dataSet = new XlsDataSet(new FileInputStream(file));String[] tableNames = dataSet.getTableNames();for (String tn : tableNames) {String[] temp = tn.split(pattern);if (temp.length == 2) {schema = temp[0];tableName = temp[1];} else {schema = this.defaultSchemaName;tableName = tn;}ITable table = dataSet.getTable(tn);if (!tableMap.containsKey(schema)) {tableMap.put(schema, new ArrayList<ITable>());}tableMap.get(schema).add(new XslTableWrapper(tableName, table));}}} catch (Exception e) {throw new UnitilsException("Unable to create DbUnit dataset for data set files: " + Arrays.toString(dataSetFiles), e);}return tableMap;} }MultiSchemaXlsDataSetReader
package com.odianyun.unitils;import org.dbunit.database.DatabaseConfig; import org.dbunit.ext.mysql.MySqlDataTypeFactory; import org.dbunit.ext.mysql.MySqlMetadataHandler; import org.unitils.core.UnitilsException; import org.unitils.dbmaintainer.locator.ClassPathDataLocator; import org.unitils.dbmaintainer.locator.resourcepickingstrategie.ResourcePickingStrategie; import org.unitils.dbunit.DbUnitModule; import org.unitils.dbunit.datasetfactory.DataSetFactory; import org.unitils.dbunit.util.DbUnitDatabaseConnection; import org.unitils.dbunit.util.MultiSchemaDataSet;import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.List;public class MyDbUnitModule extends DbUnitModule {//完善DbUnitDatabaseConnection連接信息@Overridepublic DbUnitDatabaseConnection getDbUnitDatabaseConnection(final String schemaName){DbUnitDatabaseConnection result = dbUnitDatabaseConnections.get(schemaName);if (result != null) {return result;}result = super.getDbUnitDatabaseConnection(schemaName);result.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory());result.getConfig().setProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER, new MySqlMetadataHandler());return result;}//Excel預處理操作,將@DataSet注釋讀取的文件返回給DataSetFactory進行處理@Overrideprotected File handleDataSetResource(ClassPathDataLocator locator, String nameResource, ResourcePickingStrategie strategy, Class<?> testClass) {String cloneResource = new String(nameResource);String packageName = testClass.getPackage() != null?testClass.getPackage().getName():"";String tempName = "";if(cloneResource.startsWith(packageName.replace(".", "/"))) {cloneResource = tempName = cloneResource.substring(packageName.length());} else if(cloneResource.startsWith(packageName)) {cloneResource = tempName = cloneResource.substring(packageName.length() + 1);} else {tempName = cloneResource;}InputStream in = locator.getDataResource(packageName.replace(".", "/") + "/" + tempName, strategy);File resolvedFile = null;if(in == null) {resolvedFile = this.getDataSetResolver().resolve(testClass, cloneResource);if(resolvedFile == null) {throw new UnitilsException("DataSetResource file with name '" + nameResource + "' cannot be found");}}return resolvedFile;}//調用DataSetFactory.createDataSet()向數據庫中注入Excel數據后,直接返回DataSet,不對DataSet執行清零操作@Overrideprotected MultiSchemaDataSet getDataSet(Class<?> testClass, String[] dataSetFileNames, DataSetFactory dataSetFactory) {List<File> dataSetFiles = new ArrayList<File>();ResourcePickingStrategie resourcePickingStrategie = getResourcePickingStrategie();for (String dataSetFileName : dataSetFileNames) {File dataSetFile = handleDataSetResource(new ClassPathDataLocator(), dataSetFileName, resourcePickingStrategie, testClass);dataSetFiles.add(dataSetFile);}MultiSchemaDataSet dataSet = dataSetFactory.createDataSet(dataSetFiles.toArray(new File[dataSetFiles.size()]));return dataSet;} }MyDbUnitModule
package com.odianyun.unitils;import org.apache.commons.lang.StringUtils;
import org.dbunit.dataset.*;
import org.unitils.core.UnitilsException;class XslTableWrapper extends AbstractTable {private ITable delegate;private String tableName;public XslTableWrapper(String tableName, ITable table) {this.delegate = table;this.tableName = tableName;}public int getRowCount() {return delegate.getRowCount();}public ITableMetaData getTableMetaData() {ITableMetaData meta = delegate.getTableMetaData();try {return new DefaultTableMetaData(tableName, meta.getColumns(), meta.getPrimaryKeys());} catch (DataSetException e) {throw new UnitilsException("Don't get the meta info from " + meta, e);}}public Object getValue(int row, String column) throws DataSetException {Object delta = delegate.getValue(row, column);if (delta instanceof String) {if (StringUtils.isEmpty((String) delta)) {return null;}}return delta;}} XslTableWrapper 第三步:在test下創建一個dbscripts的sql的ddl文件
我就隨便到處了數據結構的
SET FOREIGN_KEY_CHECKS=0;-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (`id` int(10) NOT NULL AUTO_INCREMENT,`name` varchar(50) COLLATE utf8_bin DEFAULT NULL,`status` int(2) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; init.sql 第四步:配置
unitils.modules=database,dbunit,spring#自定義擴展模塊,加載Excel文件,默認拓展模塊org.unitils.dbunit.DbUnitModule支持xml #unitils.module.dbunit.className=org.unitils.dbunit.DbUnitModule unitils.module.dbunit.className=com.odianyun.unitils.MyDbUnitModule#配置數據庫連接 database.driverClassName=com.mysql.jdbc.Driver database.url=jdbc:mysql://127.0.0.1:3306/dbtest?autoReconnect=true&useUnicode=true&characterEncoding=utf-8 database.userName=root database.password=root #配置為數據庫名稱 database.schemaNames=dbtest #配置數據庫方言 database.dialect=mysql#需設置false,否則我們的測試函數只有在執行完函數體后,才將數據插入的數據表中 unitils.module.database.runAfter=false#配置數據庫維護策略.請注意下面這段描述 # If set to true, the DBMaintainer will be used to update the unit test database schema. This is done once for each # test run, when creating the DataSource that provides access to the unit test database. updateDataBaseSchema.enabled=true#配置數據庫表創建策略,是否自動建表以及建表sql腳本存放目錄 dbMaintainer.autoCreateExecutedScriptsTable=true dbMaintainer.keepRetryingAfterError.enabled=true dbMaintainer.script.locations=src/test/resources/dbscripts #dbMaintainer.script.fileExtensions=sql#數據集加載策略 #CleanInsertLoadStrategy:先刪除dateSet中有關表的數據,然后再插入數據 #InsertLoadStrategy:只插入數據 #RefreshLoadStrategy:有同樣key的數據更新,沒有的插入 #UpdateLoadStrategy:有同樣key的數據更新,沒有的不做任何操作 DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy#配置數據集工廠,自定義 DbUnitModule.DataSet.factory.default=com.odianyun.unitils.MultiSchemaXlsDataSetFactory DbUnitModule.ExpectedDataSet.factory.default=com.odianyun.unitils.MultiSchemaXlsDataSetFactory#配置事務策略 commit、rollback 和disabled;或者在代碼的方法上標記@Transactional(value=TransactionMode.ROLLBACK) #commit 是單元測試方法過后提交事務 #rollback 是回滾事務 #disabled 是沒有事務,默認情況下,事務管理是disabled DatabaseModule.Transactional.value.default=commit#配置數據集結構模式XSD生成路徑,可以自定義目錄,但不能為空 dataSetStructureGenerator.xsd.dirName=src/test/resources/xsd dbMaintainer.generateDataSetStructure.enabled=true#文件相對路徑是否是測試類文件路徑,false表示resource根目錄 dbUnit.datasetresolver.prefixWithPackageName=falseunitils.properties
第五步:創建BaseUnitsTest類
package com.test;import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.unitils.UnitilsJUnit4TestClassRunner;/*** @author 危常煥* @time 2017/11/28* @description https://github.com/newsoulbr/mokitopoc/blob/master/src/test/java/com/github/newsoulbr/mokitopoc/service/PersonServiceTest.java* http://www.unitils.org/tutorial-reflectionassert.html* http://blog.csdn.net/achuo/article/details/47726241**/
@RunWith(UnitilsJUnit4TestClassRunner.class)
public class BaseUnitilsTest {protected static ApplicationContext ctx;protected static ConfigurableApplicationContext configurableContext;protected static BeanDefinitionRegistry beanDefinitionRegistry;@BeforeClasspublic static void setUpBeforeClass() {ctx = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");configurableContext = (ConfigurableApplicationContext) ctx;beanDefinitionRegistry = (DefaultListableBeanFactory) configurableContext.getBeanFactory();}public static void registerBean(String beanId, String className) {// get the BeanDefinitionBuilderBeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(className);// get the BeanDefinitionBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();// register the beanbeanDefinitionRegistry.registerBeanDefinition(beanId, beanDefinition);}/*** 移除bean* * @param beanId* bean的id*/public static void unregisterBean(String beanId) {beanDefinitionRegistry.removeBeanDefinition(beanId);}
} BaseUnitilsTest ?
第六步:準備excel:sheet是代表表名:第一列是列名:一行是一個對象
第七步:測試
package com.test;import com.po.SysRoleResource;
import com.service.SysRoleResourceService;
import com.service.impl.SysRoleResourceServiceImpl;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.unitils.dbunit.annotation.DataSet;public class TestDemo2 extends BaseUnitilsTest {private Logger logger = LoggerFactory.getLogger(this.getClass());private SysRoleResourceService sysRoleResourceService;@Beforepublic void setUp() {sysRoleResourceService = (SysRoleResourceService) ctx.getBean(SysRoleResourceServiceImpl.class);}@Test@DataSet(value = { "excel\\demo.xls" })// 通過Unitils提供的@DataSet注解從當前測試類this.class所在的目錄尋找支持DbUnit的數據集文件并進行加載。// 執行測試邏輯之前,會把加載的數據集先持久化到測試數據庫中,// @ExpectedDataSet(value = {// "com\\odianyun\\demo\\dao\\WarehouseDAOTestdemo.xls" })// 是在單元測試之后進行數據比對// 從當前測試類this.class所在的目錄尋找支持DbUnit的驗證數據集文件并進行加載,// 之后驗證數據集里的數據和數據庫中的數據是否一致public void selectByPrimaryKey() {SysRoleResource selectByPrimaryKey = sysRoleResourceService.selectByPrimaryKey(1);System.err.println(selectByPrimaryKey.getRoleId());logger.debug(selectByPrimaryKey.getRoleId() + "");};} test類 ?
轉載于:https://www.cnblogs.com/wchxj/p/8048211.html
總結
- 上一篇: 春风得意马蹄疾的下一句是什么呢?
- 下一篇: 牙齿矫正需多少钱啊?