【问题标题】:How to test the method that reads the data from the excel file in java?java中如何测试从excel文件中读取数据的方法?
【发布时间】:2016-01-11 06:43:44
【问题描述】:

上图为包含 Facebook 数据的 excel 文件。

FacebookDataExtraction 类从 Excel 文件中读取数据并将数据存储为行对象列表,如代码所示。 我已经使用 config.properties 文件来获取文件路径。 config.properties 文件内容为:FILE_NAME=D:/Refreshed_data_daily/all_hue_posts_in_excel.xlsx.

public class FacebookDataExtraction {

//private static final String FILE_NAME="D:/Refreshed_data_daily/all_hue_posts_in_excel.xlsx";
private static final String SHEET_NAME="nextv54plus_actions";
XSSFWorkbook workbook;

    public static void main(String[] args){

        FacebookDataExtraction obj= new FacebookDataExtraction();
        List<FacebookFields> displayList= new ArrayList<FacebookFields>();
        displayList=obj.readFromExcel();
        System.out.println("The Size of the list is:"+ displayList.size());
    }

    public List<FacebookFields> readFromExcel() {
        List<FacebookFields> fbList= new ArrayList<FacebookFields>();
        try
        {
            ReadPropertyFile data= new ReadPropertyFile("config.properties");
            FileInputStream fin= new FileInputStream(data.getPropertyFor("FILE_NAME"));
            workbook= new XSSFWorkbook(fin);
            int sheetIndex=0;
            for (Sheet sheet : workbook) {
                readSheet(sheet,sheetIndex ++, fbList);}

        }catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch(IOException e){
            e.printStackTrace();
        }
        return fbList;
    }

    private void readSheet(Sheet sheet, int sheetIndex , List<FacebookFields> fbList) {

        if(SHEET_NAME.equals(sheet.getSheetName())){
            workbook.removeSheetAt(sheetIndex);
            return;
        }
        for (Row row : sheet){
            if (row.getRowNum() > 0)
                fbList.add(readRow(row));}

    }

    private FacebookFields readRow(Row row) {

        FacebookFields record= new FacebookFields();
        for (Cell cell : row) {
            switch (cell.getColumnIndex()) {
            case 0: record.setName(cell.getStringCellValue()); 
            break; 
            case 1: record.setId(cell.getStringCellValue()); 
            break; 
            case 2: record.setDate(cell.getStringCellValue());
            break; 
            case 3: record.setMessage(cell.getStringCellValue());
            break; 
            case 4: record.setType(cell.getStringCellValue());
            break; 
            case 5: record.setPage(cell.getStringCellValue());
            break; 
            case 6: record.setLikeCount(String.valueOf(cell.getNumericCellValue()));
            break; 
            case 7: record.setCommentCount(String.valueOf(cell.getNumericCellValue())); 
            break; 
            case 8: record.setShareCount(String.valueOf(cell.getNumericCellValue())); 
            break; 
            }
        }

        return record;
    }

    public boolean containsData() {  

        List<FacebookFields> checkList= readFromExcel();    
        return !checkList.isEmpty() ;
    }

    }

FacebookFields 类(此处未显示)包含提取数据的设置方法! 如何编写readRow()方法的测试用例或如何测试列的每个字段是否包含数据?

【问题讨论】:

  • 单元测试?集成测试?你希望你的测试带来什么价值?
  • 你做了private的方法,也就是说它是一个内部方法。您应该尝试专注于测试该类的public 方法。如果您为公共方法设计了一个/多个良好的测试,您将自动测试私有方法是否有效。
  • @dom 我想要它的单元测试。
  • @Timo 是的私有方法无法测试。是否公开了我如何测试它?只是我想检查每列中的数据是否不为空。我该怎么做?
  • 将这个类拆分成许多只做一件事的小类(单一职责原则),然后通过构造函数注入你的依赖项,用所有小类构建你的主方法(依赖倒置原则) )。每个小类都应该可以在不了解其他类的情况下进行测试,并且会逐步建立。

标签: java junit4 properties-file testcase


【解决方案1】:
  • 因此,您想测试将返回 FacebookFields 的 readRow() 方法。
  • 由于它是私有的,你不能直接对这个私有方法进行单元测试,但你的主要目标似乎是测试这个方法。让我们在这里考虑一下重构/重新设计。
  • 你可以创建一个类FacebookFieldRetriever,它有一个公共方法retrieveFromRow(),它返回FacebookFields
  • 因此,每次FacebookDataExtraction 遇到 Excel 工作表中的一行时,它都会创建一个 FacebookFieldRetriever 对象并调用 retrieveFromRow() 以获取从该行建模的 FacebookFields 对象。
  • 我们已经通过了类设计阶段,让我们继续进行单元测试。所以,现在你有一个公共方法:retrieveFromRow(),你可以实际进行单元测试,假设你有一个行对象,其中包含包含来自 excel 工作表的实际值的单元格。 (基本上,我们专注于测试 switch-case 逻辑)。

  • FacebookFieldRetriever 类

    class FacebookFieldRetriever{
    public FacebookFields retrieveFromRow(Row row) {
    FacebookFields record= new FacebookFields(); for (Cell cell : row) { switch (cell.getColumnIndex()) { case 0: record.setName(cell.getStringCellValue()); break; case 1: record.setId(cell.getStringCellValue()); break; case 2: record.setDate(cell.getStringCellValue()); break; case 3: record.setMessage(cell.getStringCellValue()); break; case 4: record.setType(cell.getStringCellValue()); break; case 5: record.setPage(cell.getStringCellValue()); break; case 6: record.setLikeCount(String.valueOf(cell.getNumericCellValue())); break; case 7: record.setCommentCount(String.valueOf(cell.getNumericCellValue())); break; case 8: record.setShareCount(String.valueOf(cell.getNumericCellValue())); break; } }
    return record; }
    }

  • 下面的单元测试示例:

类 FacebookFieldRetrieverTest {

private final String TEST_NAME = "Mark Zuckerberg";
private final String TEST_id = "4";
private final String TEST_DATE = "2015-10-13;                                
private final String TEST_MSG = "Welcome to Facebook";                                 
private final String TEST_TYPE = "SomeType";                                
private final String TEST_PAGE = "SomePage";
private final String TEST_LIKECOUNT = 6;
private final String TEST_COMMENTCOUNT = 7;
private final String TEST_SHARECOUNT = 8 ;


public void testFacebookFieldRetriever()
{
XSSFWorkbook wb = new XSSFWorkbook();
Sheet sheettemp = wb.createSheet();
Row row = sheettemp.createRow(1);

Cell cell = row.createCell(0);
cell.setCellValue(TEST_NAME);

Cell cell1 = row.createCell(1);
cell.setCellValue(TEST_id);

Cell cell2 = row.createCell(2);
cell.setCellValue(TEST_DATE);

Cell cell3 = row.createCell(3);
cell.setCellValue(TEST_MSG);

Cell cell4 = row.createCell(4);
cell.setCellValue(TEST_TYPE);

Cell cell5 = row.createCell(5);
cell.setCellValue(TEST_PAGE);

Cell cell6 = row.createCell(6);
cell.setCellValue(TEST_LIKECOUNT);

Cell cell7 = row.createCell(7);
cell.setCellValue(TEST_COMMENTCOUNT);

Cell cell8 = row.createCell(8);
cell.setCellValue(TEST_SHARECOUNT);

FacebookFieldRetriever fbRetriever = new FacebookFieldRetriever();
FacebookFields fbFields = fbRetriever.retrieveFromRow(row);

assertEquals(fbFields.getName(), TEST_NAME);
assertEquals(fbFields.getId(), TEST_id);
assertEquals(fbFields.getMessage(), TEST_MSG);
assertEquals(fbFields.getLikeCount(), TEST_LIKECOUNT);
assertEquals(fbFields.getShareCount(), TEST_SHARECOUNT);
assertEquals(fbFields.getCommentCount(), TEST_COMMENTCOUNT);
assertEquals(fbFields.getPage(), TEST_PAGE);
assertEquals(fbFields.getType(), TEST_TYPE);
}
}

`

  • 您可以按照上面给出的方式进行测试。希望对您有所帮助。

【讨论】:

  • 问题是我不知道excel表中会出现什么数据!!因为每天都会通过软件刷新excel数据。虽然在我的测试用例中,我有一个测试来检查列表是否包含像 Tom 发布的数据!但我想要测试在行上迭代的列数据以检查其中是否存在数据
  • 您似乎暗示您不想进行单元测试,而是进行某种测试以检查 readRow() 是否实际上返回与特定行相对应的 FacebookFields。然后,我想,你应该有另一个类来解析 excel 文件,为每一行获取 FacebookFields。使用此类来测试您的 readRow(),方法是对两个对象执行一些 equals()。
  • 是的,我想做单元测试,我需要检查在行上迭代的列中读取的值是否不为空。创建另一个包含解析 excel 文件的类将具有与 FacebookDataExtraction 类中相同的提取数据的逻辑。
【解决方案2】:

如果您的 Excel 示例中的第一行包含“预期值”,则可以开始以下测试。请注意,列表的 equals 可能有点粗略,尤其是因为我不确定它如何处理元素的内部顺序。

编辑我在FacebookDataExtraction 类中添加了一个构造函数参数,该参数将文件名添加到它应该从中提取数据的excel 文件中。

@Test
public void testWhetherListConatinsData(){ 
    List<FacebookFields> expectedList = new ArrayList<>();
    // Fill the expected list here:
    expectedList.add("expected value");
    // ... Add more if you want to...

    // Read in data.
    FacebookDataExtraction fbDataList= new FacebookDataExtraction("path/to/testdata/test_with_strange_first_name.xlsx");

    List<FacebookFields> listOfFields = fbDataList.readFromExcel();
    // Good check to start with.
    assertEquals(listOfFields.containsData(), true); 

    // Actual data check.
    assertEquals("Lists not the same", expectedList, listOfFields);
} 

【讨论】:

  • excel数据是我以前不知道的,因为excel数据每天都在更新!我只知道 excel 中包含的字段,即列(第一行),即名称、id、类型等
  • 但是您应该能够创建看起来就像您将在生产中看到的那样的小型 Excel 工作表?这是完全由您控制的测试数据文件,包含您希望测试的任何内容。如果你想让它成为一个稳定的测试,你不能做一个依赖于不断变化的数据的单元测试。 (如果数据被刷新并且您的测试崩溃并且您仅在测试中强制使用新数据集后才注意到怎么办?不可重现)
  • 通过模拟 Sheet 类(公开方法)来测试方法 readSheet 是否正确?在两个单独的测试用例中测试“if”条件和 for 循环?我不知道这是否是正确的做法!
  • 可以,但我认为直接设置测试会更容易。我在示例中添加了一些内容。
猜你喜欢
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2017-03-24
  • 2023-04-01
  • 2013-10-24
  • 2016-07-17
  • 2014-03-14
  • 1970-01-01
相关资源
最近更新 更多