关于单元测试之王

第一步: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连接信息
    @Override
    public 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进行处理
    @Override
    protected 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执行清零操作
    @Override
    protected 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&amp;useUnicode=true&amp;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=false

unitils.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;

    @BeforeClass
    public 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 BeanDefinitionBuilder
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(className);
        // get the BeanDefinition
        BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        // register the bean
        beanDefinitionRegistry.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;

    @Before
    public 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类

时间: 2025-01-18 02:22:38

关于单元测试之王的相关文章

单元测试Junit

###<center> 单元测试Junit </center>###- - -1.**单元测试**:> ==单元测试==是软件之中对于最小的功能模块的的测试,其可以对最基本的软件构成单元来测试.> 需要注意的是:> >**测试用例是用来达到测试想要的预期结果,而不能测试出程序的逻辑错误**. 2.**JUnit**:>1.**Junit是基于断言机制的**.是用于编写可复用测试集的简单框架,是xUnit的一个子集.xUnit是一套基于测试驱动开发的测试

MVC与单元测试实践之健身网站(四)-动作管理

网站后台负责进行动作的管理,包括动作名称.介绍.训练要点.配图等内容,以便前台能够使用这些内容.在上一篇< Fit项目图片上传和云存储的调通>中已经准备好了这里涉及到的主要技术难点,现在就开始完成该模块了. 一 列表介绍 健身管理模块包括肌群.肌肉的显示以及动作的管理.这儿也算是开始涉及"业务内容"了,还好我之前有储备了一些关于健身的资料,现在是时候派上另一种用场了. a) 肌群和肌肉因为内容相对固定,所以为了减少业务逻辑以及单元测试的代码量,当然最主要是为了偷懒,就只提供

MVC与单元测试实践之健身网站(二)-管理员模块

开始动手做这个项目时,发现无法做到完全的先设计.再编码,于是决定分模块进行,从管理员模块开始设计.编码,而且接口就已经改了好几次了. 管理员模块涉及的功能有登录和后台对管理员的维护,其中也涉及前端的开发.UI模板使用Inspinia,感觉这套模板功能丰富.界面美观,而且基于HTML5和BootStrap,对这两方面的知识也可以多些了解. 在上一篇<如何在单元测试时隔离ORM>中,解决了对Service层进行测试怎样构建伪对象的问题,随后管理员模块的Service层和单元测试在齐头并进中完成了:

单元测试(一)-NUnit基础

单元测试作为提高代码和软件质量的有效途径,其重要性和益处自不必多说,虽然我没有实践过TDD之类,但坚信单元测试的积极作用.作为一种开发方法,单元测试早在上世纪70年代就已经在Smalltalk语言被运用了,这么多年来,单元测试一次又一次证明了自身的价值,在各种开发方式此起彼伏的浪潮中,经受住了时间的考验. 现在,俺也开始学习了,并在以后好好实践.这个系列的学习素材为Roy Osherove所著The Art of Unit Testing with examples in C#, 2nd Edi

OA项目CRUD和单元测试(一)

使用ModeFirst方法生成数据库,EntityFramework5.0. 一:Model层的模型:(根据模型生成数据库) 二:Dal层的UserInfo代码: namespace SunOA.EFDAL { public class UserInfoDal { //crud DataModelContainer db = new DataModelContainer(); public UserInfo GetUserInfoById(int id) { return db.UserInfo

词频统计-单元测试

我自己的单元测试没有弄出来,我用c编的,在visual studio中貌似实现不了单元测试,而李俞寰同学是用c#编写的词频统计,在vs2015中实现单元测试无比的方便,所以我请教了他并借鉴了一下. [TestMethod()] public void DictionarySortTest() { Dictionary<string,int>input=new Dictionary<string,int>() { {"you,1}, {"are",1},

使用Xunit来进行单元测试

不管你爱与不爱,单元测试对于一个软件的长治久安还是必不可少的一环.在Visual Studio 2012后,VS中的测试浏览器也能与第三方的集成了,用起来还是非常方便的.目前在.Net框架下的测试工具主要有Nunit.内置的MSTest以及Xunit这三个工具,本文就简单的介绍一下如何在VS中使用XUnit这个测试框架的后起之秀. 安装Xunit: Xunit的安装现在不需要插件支持了,直接使用NuGet安装如下两个库即可: PM> Install-Package xunit PM> Inst

作业八——单元测试练习(个人练习)

必做一: 针对附录1给出的三角形判断Java 代码,应用等价类划分法设计测试用例,用表格形式列出设计的测试用例: 测试用例如下:(红色字体为错误预言) 序号 测试输入:三条边 测试预言:[Oracle:Illegal(非三角形),Scalene(一般三角形), Isoceles(等腰三角形),Regular(等边三角形)] 1 (5,5,5) Regular 2 (-5,-5,-5) Regular 3 (1,4,5) Illegal 4 (2,3,5) Illegal 5 (3,4,5) Sc

作业8:单元测试练习(个人练习)

要求 [必做题1] 针对附录1给出的三角形判断Java 代码,应用等价类划分法设计测试用例,用表格形式列出设计的测试用例,写到博客中.(10分) [必做题2] 模仿附录2给出的三角形判断Junit测试代码,设计单元测试脚本,测试 [必做题1]设计得到的测试用例.注意测试脚本中测试用例出现顺序与[必做题1]表格所列顺序一致.运行所得的测试脚本,截运行结果图,写到博客中,同时将源代码push到你自己的github.(20分) [必做题3] 心得体会.写下本次练习你收获的知识点(PS:测试用例设计方法