基于spring testcontext+junit+dbunit的单元测试
/** * */ package com.um.vstore.portal.service.impl; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.Set; import javax.sql.DataSource; import net.sf.json.JSONObject; import org.dbunit.Assertion; import org.dbunit.DatabaseUnitException; import org.dbunit.database.AmbiguousTableNameException; import org.dbunit.database.DatabaseConnection; import org.dbunit.database.IDatabaseConnection; import org.dbunit.database.QueryDataSet; import org.dbunit.dataset.Column; import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ITable; import org.dbunit.dataset.ITableIterator; import org.dbunit.dataset.ITableMetaData; import org.dbunit.dataset.xml.FlatXmlDataSet; import org.dbunit.dataset.xml.FlatXmlProducer; import org.dbunit.operation.DatabaseOperation; import org.dbunit.util.fileloader.DataFileLoader; import org.dbunit.util.fileloader.FlatXmlDataFileLoader; import org.dbunit.util.fileloader.XlsDataFileLoader; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.CannotGetJdbcConnectionException; import org.springframework.jdbc.datasource.DataSourceUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.xml.sax.InputSource; import com.um.vstore.portal.domain.VPayTypeNote; import com.um.vstorel.fw.common.util.DateUtil; /** * 以VPayTypeNote为测试示例 * <p> * 这里演示数据保存、查询的单元测试示例<br> * * <li>@RunWith(SpringJUnit4ClassRunner.class):注解一个junit的运行器,该运行器是用来结合spring * test和junit的 , 它把spring test无缝运行在junit中 * <li>@ContextConfiguration(locations = { "classpath*:/applicationContext.xml" * }):配置加载spring的配置文件 * <li>@TransactionConfiguration(defaultRollback = * true):配置事物处理,是否回滚。当然,事物的回滚也可在方法前注释配置@Rollback(false/true) * * @author sg * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath*:/applicationContext.xml" }) // @TransactionConfiguration(defaultRollback = true) public class VPayNotesServiceImplTest { /** * Test method for * {@link com.um.vstore.portal.service.impl.VPayNotesServiceImpl#insert(com.um.vstore.portal.domain.VPayTypeNote)} * . */ @Autowired private VPayNotesServiceImpl payNotesService; @Autowired private DataSource dataSource; private IDatabaseConnection conn = null; private File file = null;// 数据表备份文件 private static String BACK_FILE_NAME = "paynote_back";// 备份文件名 private static String BACK_FILE_PREFIX = ".xml";// 备份文件后缀 /** * 测试前初始化,获取dbunit数据库连接,并对表做数据备份 */ @Before public void init() { conn = getDatabaseConnection("VSTORE"); // 测试前做数据备份 QueryDataSet queryDataSet = getQueryDataSet(conn, "V_P_PAYNOTE", null); try { file = File.createTempFile(BACK_FILE_NAME, BACK_FILE_PREFIX); } catch (IOException e1) { e1.printStackTrace(); }// 备份文件 try { FlatXmlDataSet.write(queryDataSet, new FileOutputStream(file)); } catch (DataSetException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { closeConnection(); } } /** * 测试完了对数据表原始数据进行还原 */ @After public void after() { InputSource xmlSource = null; try { xmlSource = new InputSource(new FileInputStream(file)); } catch (FileNotFoundException e) { e.printStackTrace(); } // 解析一个文件,产生一个数据集 FlatXmlProducer flatXmlProducer = new FlatXmlProducer(xmlSource); flatXmlProducer.setColumnSensing(true); try { conn = getDatabaseConnection("VSTORE"); // 清楚数据库数据并插入备份数据 DatabaseOperation.CLEAN_INSERT.execute(conn, new FlatXmlDataSet( flatXmlProducer)); } catch (DataSetException e) { e.printStackTrace(); } catch (DatabaseUnitException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { closeConnection(); } } /** * 测试插入操作 * <p> * 这个地方是简单的插入测试,没有使用dbunit,只是简单判断插入的动作有没有问题,并没有检查插入的数据的正确性,这种测试是不严谨的 * <p> * 这个地方可以用@Transactional来注解是否使用事物,如果用事物,则配置,不用事物则不配置 */ @Test // @Transactional public void testInsert() { VPayTypeNote payTypeNote = new VPayTypeNote(); payTypeNote.setName("测试"); payTypeNote.setNotes("测试umpay.........."); payTypeNote.setPortalNo(getId()); payTypeNote.setPayType((short) 0); payTypeNote.setStatus((short) 1); try { payNotesService.insert(payTypeNote); } catch (Exception e) { assertTrue("插入note数据异常...", false); } assertTrue("插入数据成功", true); } /** * 测试插入操作 * <p> * 这个测试操作我们采用了dbunit,测试操作的数据,我们应该在其保存或修改后,取出该条数据和我们预期的数据做对比,验证数据的正确性,当然, * 你也可以做保存失败的测试,用@ExpectedException(xxxException.class)来做 */ @Test public void testDbInsert() { // 手动设置测试数据 String no = getId(); VPayTypeNote payTypeNote = new VPayTypeNote(); payTypeNote.setNotes("db测试"); payTypeNote.setPortalNo(no); payTypeNote.setPayType((short) 0); payTypeNote.setStatus((short) 1); try { payNotesService.insert(payTypeNote); conn = getDatabaseConnection("VSTORE"); // 查询插入的数据到数据集,准备检查是否是我们插入的数据 QueryDataSet queryDataSet = getQueryDataSet( conn, "V_P_PAYNOTE", "select PAYTYPE,NOTES,STATUS from VSTORE.V_P_PAYNOTE where NOTES = 'db测试' and PAYTYPE = 0 and STATUS = 1"); if (queryDataSet == null) { assertTrue("手动设置获取queryDataSet為空", false); return; } IDataSet expected = loadXMLDataSet("/com/um/vstore/portal/service/impl/paynote_xml.xml"); if (expected == null) { assertTrue("手动设置侧四加载预期数据失败", false); return; } Assertion.assertEquals(expected, queryDataSet); } catch (Exception e) { e.printStackTrace(); } finally { closeConnection(); } } /** * 测试插入操作 * <p> * 这个测试操作我们采用了dbunit,测试操作的数据,我们应该在其保存或修改后,取出该条数据和我们预期的数据做对比,验证数据的正确性,当然, * 你也可以做保存失败的测试,用@ExpectedException(xxxException.class)来做 */ @Test public void testDbInsertFromLocal() { VPayTypeNote payTypeNote = null; // 从外部加载自定义xml或者excel数据 Map<String, Map<Integer, String>> map = loadLocalData("/com/um/vstore/portal/service/impl/note.xml"); if (map != null && map.size() != 0) { Set<String> set = map.keySet(); for (String key : set) {// 如果这个地方你知道自己定义得表数据只有一个,你可以直接获取该表数据,不用遍历所有得表 Map<Integer, String> rowMap = map.get(key); if (rowMap != null && rowMap.size() != 0) { Set<Integer> rowSet = rowMap.keySet(); for (Integer rowKey : rowSet) { String row = rowMap.get(rowKey); JSONObject jsonObj = JSONObject.fromObject(row); payTypeNote = new VPayTypeNote(); payTypeNote.setNotes(jsonObj.getString("NOTES")); payTypeNote.setPortalNo(getId()); payTypeNote.setPayType((short) jsonObj .getInt("PAYTYPE")); payTypeNote.setStatus((short) jsonObj.getInt("STATUS")); try { payNotesService.insert(payTypeNote); conn = getDatabaseConnection("VSTORE"); // 查出我们刚才插入的数据,看是否是我们刚才插入的数据 QueryDataSet queryDataSet = getQueryDataSet( conn, "V_P_PAYNOTE", "select PAYTYPE,NOTES,STATUS from VSTORE.V_P_PAYNOTE where NOTES = 'db测试--xml' and PAYTYPE = 0 and STATUS = 1"); if (queryDataSet == null) { assertTrue("自定义设置获取queryDataSet為空", false); return; } IDataSet expected = loadXMLDataSet("/com/um/vstore/portal/service/impl/note.xml"); if (expected == null) { assertTrue("自定义设置侧四加载预期数据失败", false); return; } // 这个地方用的是dbunit的断言,比较两个数据集 Assertion.assertEquals(expected, queryDataSet); } catch (Exception e) { e.printStackTrace(); } finally { closeConnection(); } } } else { assertTrue("表格[" + key + "]获取行数据异常", false); } } assertTrue("获取行xml数据正常", true); } else { assertTrue("xml测试数据没有获取到值", false); } } /** * 测试数据查询 * <p> * 我们定义一个预期的数据,该数据通过dbunit初始化到数据库中,然后我们通过查询检索出这些数据,和预期数据做个对比,看我们的检索是否正确 */ @Test public void testSearchForPrimaryKey() { // 加载自定义的预期数据 IDataSet ds = loadXMLDataSet("/com/um/vstore/portal/service/impl/search_note.xml"); try { conn = getDatabaseConnection("VSTORE"); // 把准备的预期数据通过dbunit持久化到数据库表中 DatabaseOperation.CLEAN_INSERT.execute(conn, ds); } catch (DatabaseUnitException e1) { e1.printStackTrace(); } catch (SQLException e1) { e1.printStackTrace(); } try { VPayTypeNote note = payNotesService.searchForPrimaryKey("10000001", (short) 0, (short) 1); if (note == null) { assertTrue("查询测试失败", false); } else { assertTrue(true); } } catch (Exception e) { e.printStackTrace(); assertTrue(false); } finally { closeConnection(); } } /** * 测试获取excel中的数据 * <p> * 获取excel中的测试数据,封装该数据可以用来测试外部提供数据进行批量插入,及查询等的预期数据 * <p> * 这个dbunit需要依赖poi3.2的包 */ @Test public void testExcelLoad() { Map<String, Map<Integer, String>> map = loadLocalData("/com/um/vstore/portal/service/impl/note.xls"); if (map != null && map.size() != 0) { Set<String> set = map.keySet(); for (String key : set) { Map<Integer, String> rowMap = map.get(key); if (rowMap != null && rowMap.size() != 0) { Set<Integer> rowSet = rowMap.keySet(); for (Integer rowKey : rowSet) { String row = rowMap.get(rowKey); System.out.println(row); } } else { assertTrue("表格[" + key + "]获取行数据异常", false); } } assertTrue("获取行excel数据正常", true); } else { assertTrue("excel测试数据没有获取到值", false); } } @Test /** * 测试获取xml中的数据 * <p> * 获取xml中的测试数据,封装该数据可以用来测试外部提供数据进行批量插入,及查询等的预期数据 * <p> * 这个dbunit需要依赖poi3.2的包 */ public void testXMLLoad() { Map<String, Map<Integer, String>> map = loadLocalData("/com/um/vstore/portal/service/impl/note.xml"); if (map != null && map.size() != 0) { Set<String> set = map.keySet(); for (String key : set) { Map<Integer, String> rowMap = map.get(key); if (rowMap != null && rowMap.size() != 0) { Set<Integer> rowSet = rowMap.keySet(); for (Integer rowKey : rowSet) { String row = rowMap.get(rowKey); JSONObject obj = JSONObject.fromObject(row); System.out.println(obj.getString("NOTES") + "||" + obj.getInt("PAYTYPE")); } } else { assertTrue("表格[" + key + "]获取行数据异常", false); } } assertTrue("获取行xml数据正常", true); } else { assertTrue("xml测试数据没有获取到值", false); } } /** * 加载本地excel或者xml得数据方法,用以提供预期数据 * <p> * 该方法获取本地excel或者xml得数据,用以提供测试用例数据,方法返回一个以数据表为单位得map对象,key值为表名(sheet名), * value为每个表得数据得map对象 * ,该map存储了该表得所有数据,这个map以行为单位,key值为从1开始得行号,vaule为每行得数据,格式为json字符串 * ,如:{name:"umpay";age:10} * * @param dataPath * 本地数据表格路径,该地址是相对工程的绝对路径,比如:/com/um/vstore/service/impl/note. * xls * @return 返回一个以表为单位得map对象 */ private Map<String, Map<Integer, String>> loadLocalData(String dataPath) { DataFileLoader loader = null; if (dataPath.endsWith(".xml")) { loader = new FlatXmlDataFileLoader(); } else if (dataPath.endsWith(".xls")) { loader = new XlsDataFileLoader(); } if (loader != null) { IDataSet ds = loader.load(dataPath); try { ITableIterator iterator = ds.iterator(); Map<String, Map<Integer, String>> tableMap = new HashMap<String, Map<Integer, String>>(); // 遍历有多少个表 while (iterator.next()) { ITable table = iterator.getTable(); // 这里的行数已经在table中被dbunit给去掉了头,所以这里返回的行数是不包含标题头的,它是真实数据的行数 int row = table.getRowCount(); if (row >= 1) {// 有数据才遍历 ITableMetaData tableMetaData = table.getTableMetaData(); String tableName = tableMetaData.getTableName();// 获取表名,即sheet得名称 // 获取列名 Column[] columns = table.getTableMetaData() .getColumns(); Map<Integer, String> rowMap = new HashMap<Integer, String>(); for (int i = 0; i < row; i++) { JSONObject jsonRow = new JSONObject(); for (Column column : columns) { String columnName = column.getColumnName(); // rowValue = String.valueOf(table.getValue(i, // columnName)); jsonRow.put(columnName, table.getValue(i, columnName)); rowMap.put(i + 1, jsonRow.toString()); } } tableMap.put(tableName, rowMap); } } return tableMap; } catch (DataSetException e) { e.printStackTrace(); } } return null; } /** * 生成一个随机数作为id * * @return */ private String getId() { StringBuffer id = new StringBuffer(); id.append(DateUtil.getDateAndTime()); Random random = new Random(); // 保证这个随机码的位数是4位的 int num = random.nextInt(10000); random.setSeed(111222333); id.append(String.format("%04d", num)); return id.toString(); } /** * dbunit数据库连接关闭 */ private void closeConnection() { if (conn != null) { try { conn.close(); conn = null; } catch (SQLException e) { e.printStackTrace(); } } } /** * 通过dbunit获取数据查询的结果 * <p> * 通过dbunit获取数据查询的结果,将结果封装到DataSet中,便于和我们预期的值(自定义xml中数据)比较 * * @param conn * dbunit数据库连接对象 * @param resultName * 结果集名,要和自定义的预期xml中的标签名一致 * @param querySql * 你想要的查询的sql,可以为空,为空的时候是查的整个表,把整个表数据查出放到数据集中 * @return */ private QueryDataSet getQueryDataSet(IDatabaseConnection conn, String resultName, String querySql) { if (resultName == null || resultName == "") { return null; } QueryDataSet actual = new QueryDataSet(conn); try { if (querySql != null && querySql != "") { actual.addTable(resultName, querySql); } else { actual.addTable(resultName); } return actual; } catch (AmbiguousTableNameException e) { e.printStackTrace(); } return null; } /** * 获取dbunit数据库连接对象 * * @param dataBaseName * 数据库名称(schema) * @return */ private IDatabaseConnection getDatabaseConnection(String dataBaseName) { try { IDatabaseConnection connection = new DatabaseConnection( DataSourceUtils.getConnection(dataSource), "VSTORE"); return connection; } catch (CannotGetJdbcConnectionException e) { e.printStackTrace(); } catch (DatabaseUnitException e) { e.printStackTrace(); } return null; } /** * 加载本地准备的xml数据 * * @param xmlPath * xml数据文件地址,该地址是相对工程的绝对路径,比如:/com/um/vstore/service/impl/ * mydata_xml.xml * @return */ private IDataSet loadXMLDataSet(String xmlPath) { if (xmlPath == null || xmlPath == "") { return null; } if (!xmlPath.endsWith(".xml")) { return null; } DataFileLoader loader = new FlatXmlDataFileLoader(); IDataSet ds = loader.load(xmlPath); return ds; } @Test public void testLoadXML() { loadXMLDataSet("/com/um/vstore/portal/service/impl/paynote_xml.xml"); } }
相关推荐
`Junit` 和 `dbunit` 是两个非常重要的工具,它们分别针对Java应用程序的单元测试和数据库测试提供支持。让我们详细了解一下这两个库以及如何将它们结合使用。 `Junit` 是一个流行的开源Java单元测试框架,由Ernst ...
在Spring框架中,进行Dao层的集成单元测试时,常常会结合Dbunit工具来实现数据库相关的测试。Dbunit是一款强大的Java库,它扩展了JUnit,为数据库提供了结构化数据的导入和导出,使得测试更加方便和可靠。下面将详细...
在软件开发中,Spring框架是Java企业级应用的主流选择,而DBUnit则...这些代码可能包含了Spring测试类的示例、数据集文件和DBUnit的使用方式。通过对这些代码的分析和学习,可以更直观地理解Spring与DBUnit的集成过程。
DBUnit 是一个用于数据库单元测试的开源库,它允许开发者在测试前后设置和清理数据库状态,以确保测试的隔离性和准确性。这篇文章将详细介绍如何在 Spring Boot 项目中集成和使用 DBUnit。 首先,为了在 Spring ...
一个使用数据库的单元测试示例以及它所需的少量工具的实现。 JUnit4 DBUnit(原始定制) 弹簧框架 spring-test-dbunit(产品名称) 的情况下的组合是先决条件。 此外,示例数据库类型是 MySQL。 最新整合 大师: ...
1. **测试框架的使用**:项目可能使用了JUnit作为基本的单元测试框架,用于编写和执行测试用例。JUnit是Java中最常用的测试工具,它提供了断言、注解和测试套件等特性,方便编写测试代码。 2. **Mocking技术**:...
DBUnit 是一个开源的Java库,它扩展了JUnit框架,为数据库测试提供了强大的支持。这个压缩包"dbunit-2.1.zip"包含了DBUnit 2.1版本的相关文档,帮助用户理解和使用这个数据库测试工具。尽管描述部分的文本似乎无效,...
Spring DBUnit 提供了 Spring 测试框架和 DBUnit 项目,允许你通过注解来实现测试的一些准备工作。 示例代码: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration @TestExecutionListeners({ ...
- **JUnit**: JUnit是最早也是最广泛使用的Java单元测试框架之一,主要用于编写和运行测试用例。它支持注解驱动的测试方法,但其版本迭代相对缓慢,部分高级特性支持不如新框架。 - **TestNG**: TestNG是一个基于...
例如,JUnit是最基础的单元测试框架,适合对单个类或方法进行测试;TestNG则提供了更丰富的功能,如并行测试、测试套件管理等。对于更复杂的集成测试和端到端测试,我们可以选择Selenium WebDriver,它支持多种...
使用JUnit和Mockito进行单元测试,通过Spring Test和DBUnit进行集成测试,确保代码的质量和稳定性。 六、代码质量管理与重构 SpringSide 4 遵循良好的编码规范,如SOLID原则,以及代码重构的最佳实践。通过学习...
MongoDB 是一款流行的开源、分布式文档型数据库,而 DbUnit 是 Java 开发中的一个单元测试框架,主要用于数据库的数据填充和验证。当这两者结合时,便形成了 dbunit-mongodb 模块,它为 MongoDB 提供了类似于 DbUnit...
Spring Test是Spring框架的一部分,提供了对单元测试和集成测试的支持。结合DBUnit,它可以为Spring应用程序提供强大的数据库测试能力。 在实际应用中,使用Spring Test和DBUnit进行数据库测试通常包括以下步骤: ...
DBUnit是一个开源的Java库,专门用于简化数据库的单元测试,它可以自动化填充和清理数据库状态,确保每次测试都能在一致的数据环境中运行。下面将详细阐述Spring与DBUnit的结合使用及其相关知识点。 1. **Spring ...
1. **单元测试**:Java中的单元测试通常使用JUnit或TestNG框架进行。开发者编写测试用例来验证单个方法或组件的功能,确保代码质量。 2. **集成测试**:当多个组件协同工作时,集成测试用于检查它们之间的交互。...
dbUnit 是一个 JUnit 扩展,专门设计用来处理数据库测试。它允许开发者在测试前后设定和清理数据库状态,确保测试的隔离性和准确性。dbUnit 支持多种数据格式(如 XML、CSV 和 Excel),可以方便地导入和导出数据集...
1. **单元测试**:单元测试是对程序中最小可测试单元进行检查和验证,如函数、方法或类。使用JUnit这样的框架,我们可以编写测试用例来验证特定方法的行为。例如,我们可以创建一个测试类,针对映射器中的每个方法...
- JUnit:虽然主要用于单元测试,但可以结合其他库如DBUnit进行数据库测试。 - DBUnit:提供了一种结构化的数据导入和导出机制,便于设置和验证数据库状态。 - Hibernate Tools:包含了一个JUnit测试框架,可进行...
8. **单元测试和集成测试**:为了确保代码质量,项目可能会使用JUnit、Mockito等工具进行单元测试,以及使用如Spring Boot Test、DBUnit等进行数据库相关的集成测试。 9. **日志记录**:日志系统如Log4j、SLF4J或...