Junit5结合数据驱动 excel
JUnit5结合数据驱动-excel
excel 解析对比
| 解析方式 | 说明 |
|---|---|
| JXL | 开源的 Java Excel API 项目 2011 后未更新 |
| JExcel | 不是 JXL 2019 后未更新 |
| Apache POI | 官网 支持 xls、xlsx 社区强大,更新快,至今还在更新 |
pom 导入相关依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<!-- 使用 Java 11 语言特性 ( -source 11 ) 并且还希望编译后的类与 JVM 11 ( -target 11 )兼容,您可以添加以下两个属性,它们是默认属性插件参数的名称-->
<maven.compiler.target>11</maven.compiler.target>
<maven.compiler.source>11</maven.compiler.source>
<!-- 对应junit Jupiter的版本号;放在这里就不需要在每个依赖里面写版本号,导致对应版本号会冲突-->
<junit.jupiter.version>5.8.2</junit.jupiter.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
<maven.surefire.version>3.0.0-M5</maven.surefire.version>
<!-- plugins -->
<maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
<poi.version>5.2.2</poi.version>
</properties>
<!-- 物料清单 (BOM)-->
<dependencyManagement>
<dependencies>
<!--当使用 Gradle 或 Maven 引用多个 JUnit 工件时,此物料清单 POM 可用于简化依赖项管理。不再需要在添加依赖时设置版本-->
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit.jupiter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<!-- 对应添加的依赖的作用范围-->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
poi 解析步骤
- 1、获取文件名后缀
- 2、查看文件是否存在
- 3、获取工作薄对象
Workbook- 如果是
xls结尾用HSSF - 如果是
xlsx结尾用XSSF
- 如果是
- 4、读取第一个
sheet - 5、获取行
- 6、读取每一行的单元格内容
- 7、最后关闭流
1、获取文件名后缀
我们需要先判断一下这个文件是否时 excel 文件,excel 文件的后缀有两种形式,.xls 和.xlsx
String pathname = "src/test/resources/orderLine.xlsx";
//substring截取左闭右开,从最后一个.右侧的位置到pathname末尾。
String excelType = pathname.substring(pathname.lastIndexOf(".") + 1, pathname.length());
assertThat("当前文件不是excel文件",excelType,anyOf(endsWithIgnoringCase("xlsx"),endsWithIgnoringCase("xls")));
2、查看文件是否存在
除了检查文件是否是 excel 文件,还需要检查这个文件是否存在,不存在的文件没有必要继续向下执行。
//2.查看当前文件是否存在
File file=new File(pathname);
assertTrue(file.exists(),"文件不存在");
3、获取工作薄对象 Workbook
- 使用输入流的形式打开文件获取工作薄对象
- 直接使用 file 打开文件获取工作薄对象
//3.获取workbook
FileInputStream stream = new FileInputStream(file);
Workbook workbook =null;
//针对不同后缀的文件,获取方式也不同,所以需要做一个if判断
//equalsIgnoreCase表示忽略大小判断是否相等
if(excelType.equalsIgnoreCase("xls"))
{
//如果文件是xls的后缀,应该以HSSF声明
workbook = new HSSFWorkbook(stream);
}
else if(excelType.equalsIgnoreCase("xlsx")){
workbook = new XSSFWorkbook(stream);
}
4、获取 sheet
- 想要获取哪个就读取哪个 sheet
- 获取当前工作薄有几个 sheet 标签页
//4.获取sheet
//对应sheet页从0开始,int类型
Sheet sheet=workbook.getSheetAt(0);
//获取当前工作簿中一共有几个sheet
int numberOfSheets= workbook.getNumberOfSheets();
获取行数
- 获取 sheet 中有多少行
- 一个 sheet 里面有多个 row
for(Row row:sheet ){
////为每一行创建一个数组存放内容,data中每个元素都为一个数组
data.put(i,new ArrayList<>());
}
获取每一个单元格数据
在获取行的循环中嵌套一个循环来获取单元格数据
-
一行「row」有多个单元格「Cell」
//map<行号,list是行内容> Map<Integer, List<Object>> data = new HashMap<>(); int i = 0; for (Row row : sheet) { //{0=[]} data.put(i, new ArrayList<Object>()); for(Cell cell:row){ //[] //每一个单元格就是ArrayList里面一个元素 List<Object> objectList = data.get(i); objectList.add(cell); } i++; } System.out.println("data:" + data);
- 如果控制台出现报错信息如下图

- 需要在 pom.xml 文件中添加 log4j-core 依赖(不添加无影响)
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
- 读取数据完整代码
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.FileInputStream;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.endsWithIgnoringCase;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ExcelTest {
@Test
void excelBaseTest() {
try {
//1.获取文件名后缀
String pathname = "src/test/resources/orderLine.xlsx";
//substring截取左闭右开,从最后一个.右侧的位置到pathname末尾。
String excelType = pathname.substring(pathname.lastIndexOf(".") + 1, pathname.length());
assertThat("当前文件不是excel文件",excelType,anyOf(endsWithIgnoringCase("xlsx"),endsWithIgnoringCase("xls")));
//2.查看当前文件是否存在
File file=new File(pathname);
assertTrue(file.exists(),"文件不存在");
//3.获取workbook
FileInputStream stream = new FileInputStream(file);
Workbook workbook =null;
//针对不同后缀的文件,获取方式也不同,所以需要做一个if判断
//equalsIgnoreCase表示忽略大小判断是否相等
if(excelType.equalsIgnoreCase("xls"))
{
//如果文件是xls的后缀,应该以HSSF声明
workbook = new HSSFWorkbook(stream);
}
else if(excelType.equalsIgnoreCase("xlsx")){
workbook = new XSSFWorkbook(stream);
}
//4.获取sheet
//对应sheet页从0开始,int类型
Sheet sheet=workbook.getSheetAt(0);
//获取当前工作簿中一共有几个sheet
int numberOfSheets= workbook.getNumberOfSheets();
//5.获取行
//一个sheet对应的Java数据结构
//每一行都是一个对象
//Map<Integer, List<Object>> 对应 Map<行号,行的内容 >
Map<Integer, List<Object>> data= new HashMap<>();
//当前sheet中一共有多少行
int numberOfRows = sheet.getPhysicalNumberOfRows();
int i=0;//表示行号
for(Row row:sheet ){
//为每一行创建一个数组存放内容
data.put(i,new ArrayList<>());
//6、获取每一行的单元格的内容
int physicalNumberOfCells = row.getPhysicalNumberOfCells();
for (Cell c:row){
//通过将索引为`i`的元素赋值给`objects`,可以在后续的代码中使用`objects`来访问和操作该元素的内容。
//修改`objects`对象中的值时,会对`data`列表中的数据产生影响。这是因为`objects`实际上是指向`data.get(i)`所返回的列表的引用。
List<Object> objects = data.get(i);
objects.add(c);//将数据存入data中
}
i++;
// System.out.println("physicalNumberOfCells-----"+physicalNumberOfCells);
}
System.out.println(data);
//7、关闭流
workbook.close();
}catch (Exception e){
throw new RuntimeException(e);
}
}
}
- 效果如下

数据解析类型
目前我们可以正常读取数据了,但是可以看到日期的格式不规范,如果需要完善,可以添加以下代码
- excel 可以设置列的数据类型
switch (cell.getCellType()) { //单元格类型枚举值为STRING时,将使用Cell接口的getRichStringCellValue()方法读取内容: //文本格式的内容读取 case STRING: cell.getRichStringCellValue().getString(); break; // 数字、日期 case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { //日期型以年-月-日格式存储 SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd"); fmt.format(cell.getDateCellValue()); } else { cell.getNumericCellValue(); } break; case BOOLEAN: cell.getBooleanCellValue(); break; case FORMULA: cell.getCellFormula(); break; default: data.get(Integer.valueOf(i)).add(" "); }