Junit5-数据驱动

Junit5-数据驱动

Java5+maven3.8+idea2022.2

junit5可以通过文件加载数据,如下4种文件加载数据

  • yaml
  • excel
  • csv
  • json

1. 解析yaml文件数据

   首先要加载依赖到pom.xml,下面解析yaml需要这些依赖
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.13.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.dataformat</groupId>
      <artifactId>jackson-dataformat-yaml</artifactId>
      <version>2.13.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.datatype</groupId>
      <artifactId>jackson-datatype-jsr310</artifactId>
      <version>2.13.0</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
       <version>2.12.1</version>
    </dependency>

在resources下创建 yaml文件,里面以key value 的形式 存放数据,如下所示:

#这是个list 一个-代表一个对象
- item: No. 9 Sprockets
  quantity: 12
  price: 1.23
  date: 2019-04-17
- item:  No. Widget (10mm)
  quantity: 10
  price: 3.45
  date: 2022-01-16

Yaml文件中数据格式是Key Value格式,因此可以解析到Map中以key value的形式存储,也可以解析到一个与yaml数据相似的结构体中
首先看到上面的yaml文件里包含2组数据,如果解析成对象的话就是2个对象,解析成Map的话,就是2个Map,看下面代码,介绍这2种解析方式

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.zqh.pojo.PlanInfo;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

public class YamlTest {
    String url = "src/test/resources/orderlist.yaml";
    @Test
    //使用Map key value的形式接收数据
    //yaml中是2组数据,因此这里定义List来存放Map
    void listTest() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
        //解析yaml文件内容
        TypeReference<List<HashMap<String, String>>> typeReference =
                new TypeReference<List<HashMap<String, String>>>() {
        };

       List<HashMap<String,String>> list= objectMapper.readValue(new File(url),typeReference);  //读取yaml文件 并解析到 typeReference

        System.out.println(list);

    }
    @Test
    //使用实体类对象的形式接收yaml数据,
    //yaml中的key名称应该与实体类的参数名一一对应
    //成员变量与yaml里的key不一致时,实体类使用注解@JsonProperty("item")来做映射
    void PlanTest() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
        //objectMapper.findAndRegisterModules();//为了正常处理 日期类型
        //将yaml文件的内容 转换为实体类
        TypeReference<List<PlanInfo>> typeReference =
                new TypeReference<List<PlanInfo>>() {
        };
        List<PlanInfo> infos = objectMapper.readValue(new File(url), typeReference);
        System.out.println(infos);
    }
}

这个实体类必须要有无参构造方法,并如果yaml里的key与实体类的参数名不一致的时候需要使用注解 @JsonProperty(“item”)来显示声明 yaml的key对应哪一个参数,如果两者的名称一致,可以不适用此注解,将会自动对应解析


import java.math.BigDecimal;
import java.time.LocalDate;

/**
 * 使用注解 JsonProperty,来匹配实体类字段
 */
public class PlanInfo {
    @JsonProperty("item")
    private String item;
    @JsonProperty("quantity")
    private int quantity;
    @JsonProperty("price")
    private BigDecimal price;
    @JsonProperty("date")
    private LocalDate date;

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return super.toString();
    }
    public PlanInfo(){

    }
    public PlanInfo(String item,int quantity,LocalDate date,BigDecimal price){
        this.item = item;
        this.date = date;
        this.price = price;
        this.quantity = quantity;
    }
}

2. 加载excel

     这里解析excel使用的是 apache poi 依赖
   <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>5.2.2</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>5.2.2</version>
    </dependency>

poi解析步骤:
获取工作簿的对象Workbook 区分文件类型 如果是xls后缀要使用HSSF 如果是xlsx结尾要用XSSF
1获取文件名后缀->2验证文件是否存在->3获取工作簿的对象Workbook-> 4读取第一个sheet->获取行->5读取每一行的单元格内容->6最后关闭流
excel里的内容如下:
在这里插入图片描述
用代码实现上面步骤

public class ExcelParamTest {
    String filePath = "src/test/resources/param.xlsx";

    @Test
    //读取excel表格中的数据
    public void ReadExcel() throws IOException {
        //步骤一 获取文件后缀名,截取.后面的到文件最后这一段字符串,判断文件后缀
        String suffix = filePath.substring(filePath.lastIndexOf(".") - 1, filePath.length());
        assertThat("改文件不是excel", suffix, is(anyOf(endsWithIgnoringCase("xlsx"), endsWithIgnoringCase("xls"))));
        //步骤二 判断文件是否存在
        File file = new File(filePath);
        assertTrue(file.exists(), "文件不存在");
        //步骤三 获取工作簿对象
        Workbook workbook = null;
        FileInputStream io = new FileInputStream(file);
        if (suffix == "xlsx") {
            workbook = new XSSFWorkbook();
        } else {
            workbook = new HSSFWorkbook();
        }
        //步骤四 读取sheet页
        Sheet sheet = new workbook.getSheetAt(0);//获取第一个sheet对象
        int numOfSheets = workbook.getNumberOfSheets();//当前有几个sheet页
        int numOfRows = sheet.getPhysicalNumberOfRows();//这个sheet有多少行

        //步骤五 读取每一个单元格
        //将数据放在 map里 key是行号,value是list
        HashMap<Integer, List<Object>> map = new HashMap<>();
        int i = 0;
        for (Row row : sheet) {
            map.put(i, new ArrayList<>());
            int numOfCells = row.getPhysicalNumberOfCells();
            for (Cell cell : row) {
                List<Object> objects = map.get(i);
                //objects.add(cell);
                CellType type = cell.getCellType();
                Object cellValue = getCellValue(cell);
                objects.add(cellValue);

            }
            i++;
        }
        workbook.cloneSheet(0);
        workbook.close();

    }

    public Object getCellValue(Cell cell) {
        CellType cellType = cell.getCellType();
        switch (cellType) {
            case STRING: //字符串
                String str = cell.getRichStringCellValue().toString();
                return str;
            case NUMERIC://数字 日期
                if (判断是日期) {//判断是日期
                    SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
                    return fmt.format(cell.getDateCellValue());
                } else {
                    return cell.getNumericCellValue();
                }
            case BOOLEAN:
                return cell.getBooleanCellValue();
            case FORMULA:
                return cell.getCellFormula();
            default:
                return null;
        }
    }
}

3. 加载csv文件数据

需要先加载csv使用的依赖到pom.xml,如下:
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-csv</artifactId>
            <version>2.13.1</version>
        </dependency>

声明一个实体类 ,包含的字段与csv的header一致
在这里插入图片描述

import java.math.BigDecimal;
import java.time.LocalDate;

public class ParamInfo {
    private String item;
    private int quantity;
    private BigDecimal price;
    private LocalDate date;

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public ParamInfo(String item, int quantity, BigDecimal price, LocalDate date) {
        this.item = item;
        this.quantity = quantity;
        this.price = price;
        this.date = date;
    }

    public ParamInfo() {
    }

    @Override
    public String toString() {
        return "CSVParamTest{" +
                "item='" + item + '\'' +
                ", quantity=" + quantity +
                ", price=" + price +
                ", date=" + date +
                '}';
    }
}

csv的第一行一般用来放参数名,从第二行开始放参数值
将csv的header映射给实体类的字段可以看出csv有2行数据,因此对应2个对象,使用MappingIterator来接收多个对象
下面的代码是,当csv的header与实体类的参数一一对应的情况

public class CSVParamTest {
    String url = "src/test/resources/params.csv";
    @Test
    public void readCsv() throws IOException {

        CsvMapper csvMapper = new CsvMapper();
        //CsvSchema 读取csv的模式 这里是使用header读取
        CsvSchema orderLineSchema  = CsvSchema.emptySchema().withHeader();//带着header读取
        //csvMapper.findAndRegisterModules();//这个用来正确处理日期类型
        //用一个迭代器接收数据,用header映射实体类的参数
        MappingIterator<ParamInfo> params = csvMapper.readerFor(ParamInfo.class)
                .with(orderLineSchema).readValues(new File(url));

        System.out.println(params);
    }
}

有时候csv字段与实体类的字段并不一致,需要手动映射
在实体类上的参数上增加注解@JsonProperty(“csv中字段名称”)

另外可以过滤掉首行也就是header头,再自己定义header,如下看代码:

 @Test
    public void readCsv2() throws IOException {
        CsvMapper mapper = new CsvMapper();
        //setSkipFirstDataRow(true) 不解析第一行 csv header 手动给按照顺序增加表头
        CsvSchema schema = CsvSchema.builder().setSkipFirstDataRow(true)
                .addColumn("item")
                .addColumn("quantity")
                .addColumn("price")
                .addColumn("date")
                .build();
        MappingIterator<Object> mapping = mapper.readerForMapOf(String.class)
                .with(schema)
                .readValues(new File(url));

        System.out.println(mapping.readAll());
    }

4. 解析json

   json文件的数据读取与yaml相似
   所需要的依赖也与yaml一样,这里不重复写了,直接上代码
   定义json文件1,json文件内容如下,是一个数组,数组里有2条数据
[
  {
    "item":"No.9 sss",
    "quantity":12,
    "price": 4,
    "date": "2022-08-17"
  },
  {
    "item":"No.10 lal",
    "quantity":13,
    "price": 7,
    "date": "2022-08-17"
  }
]

定义json文件2,如下所示,只有一条数据,但是其中内部有一个数组

{
  "orderNo": "A001",
  "date": "2022-08-17",
  "customerName": "Customer,joe",
  "orderLines": [
    {
      "item": "No.10",
      "quantity": 12,
      "price": 2.3
    },
    {
      "item": "No.11",
      "quantity": 17,
      "price": 2.5
    }
  ]
}

下面介绍,将上面的json解析成k-v形式的map以及解析成实体类,因此定义json对应的实体类
实体类1对应json1,json的key与实体类的参数名一一对应

import com.fasterxml.jackson.annotation.JsonProperty;

import java.math.BigDecimal;
import java.time.LocalDate;

public class ParamInfo {
    @JsonProperty("item")
    private String item;
    @JsonProperty("quantity")
    private int quantity;
    @JsonProperty("price")
    private BigDecimal price;
    @JsonProperty("date")
    private LocalDate date;


    public ParamInfo(String item, int quantity, BigDecimal price, LocalDate date) {
        this.item = item;
        this.quantity = quantity;
        this.price = price;
        this.date = date;
    }

    public ParamInfo() {
    }

    @Override
    public String toString() {
        return "CSVParamTest{" +
                "item='" + item + '\'' +
                ", quantity=" + quantity +
                ", price=" + price +
                ", date=" + date +
                '}';
    }

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }

    public int getQuantity() {
        return quantity;
    }

    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }
}

实体类2,对应json2,他们的名称也是一一对应的,因此不写注解了

import java.time.LocalDate;
import java.util.List;

public class ParamInfo2 {
    private String orderNo;
    private LocalDate date;
    private String customerName;
    List<ParamInfo> orderLines;

    public ParamInfo2() {
    }

    public ParamInfo2(String orderNo, LocalDate date, String customerName, List<ParamInfo> orderLines) {
        this.orderNo = orderNo;
        this.date = date;
        this.customerName = customerName;
        this.orderLines = orderLines;
    }

    @Override
    public String toString() {
        return "ParamInfo2{" +
                "orderNo='" + orderNo + '\'' +
                ", date=" + date +
                ", customerName='" + customerName + '\'' +
                ", orderLines=" + orderLines +
                '}';
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public String getCustomerName() {
        return customerName;
    }

    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }

    public List<ParamInfo> getOrderLines() {
        return orderLines;
    }

    public void setOrderLines(List<ParamInfo> orderLines) {
        this.orderLines = orderLines;
    }
}

下面的代码介绍将2种json解析成map和结构体

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import pojo.ParamInfo;
import pojo.ParamInfo2;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.List;

public class JsonParamTest {
    String url  = "src/test/resources/params.json";
    String url2 = "src/test/resources/params2.json";
    @Test
    //json1 解析到HashMap中,由于有2组数,因此放入List
    public void JsonTest() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
        objectMapper.findAndRegisterModules();//为了正常处理 日期类型
        TypeReference<List<HashMap<String,Object>>> ref =  new TypeReference<List<HashMap<String, Object>>>() {
        };
        List<HashMap<String,Object>> list  = objectMapper.readValue(new File(url),ref);
        System.out.println(list);
    }

    @Test
    //json1 使用实体类解析,json中包含2个对象,使用List接收
    public  void JsonTest2() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
        objectMapper.findAndRegisterModules();//为了正常处理 日期类型
        TypeReference<List<ParamInfo>> ref =  new TypeReference<List<ParamInfo>>() {};
        List<ParamInfo> list  = objectMapper.readValue(new File(url),ref);
        System.out.println(list);
    }
    @Test
    //json2解析 到map
    //这次就一个对象,因此用Map接收,不用使用List
    public  void JsonTest3() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
        //objectMapper.findAndRegisterModules();//为了正常处理 日期类型
        TypeReference<HashMap<String,Object>> ref =  new TypeReference<HashMap<String, Object>>() {
        };
        HashMap<String,Object> map = objectMapper.readValue(new File(url2),ref);
        System.out.println(map);
    }
    @Test
    //json2 解析成结构体,这里只有一条数据因此使用一个对象接收数据即可
    public void JsonTest4() throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
        TypeReference<ParamInfo2> ref =  new TypeReference<ParamInfo2>() {};
        objectMapper.findAndRegisterModules();//为了正常处理 日期类型
        ParamInfo2 info = objectMapper.readValue(new File(url2),ref);
        System.out.println(info.toString());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值