java - 如何通过读取文件并将其写入另一个文件来为我的类(class)编写单元测试?

标签 java spring testing readfile writefile

我需要读取 xlsx 文件并将输出与 SQL 语句结合写入文件。

要求如下:

  1. 文件位于 C 盘的特定文件夹中。
  2. 在文件中,第一列和第三列应该没有标题。
  3. 一个 SQL 语句将与之前的输出一起写入一个文件。

到目前为止,这是可行的。我不得不用 JAVA8 Springboot 来实现它。随函附上我已经上传了我的 MainClass、ExcelReader 类、aapplication.properties 和 pom.xml

我现在不明白我是如何为它创建单元测试的。我是否必须将我的类拆分为多个方法,因为在一个方法 readInputFileWriteSQLStatements() 中,读取文件,过滤列并填充新文件。

我应该在这些方法中写入哪些参数? 单元测试是什么样子的?

第一次尝试:

首先我在Mainclass里设置了path属性,然后把Class ExcelReader里的参数给readInputFileWriteSQLStatements(String filePath);但结果为 NULL。然后我尝试编写一个 TestClass,其路径为 test/resource/目录,但这没有成功,因为 NULL 指针异常

@Value("${filepath}")
private static String filePath;

public static void main(String[] args) throws IOException, InvalidFormatException {

    SpringApplication sa = new SpringApplication(MainClass.class);

    ApplicationContext c = sa.run(args);
    ExcelReader bean = c.getBean(ExcelReader.class);
    bean.readInputFileWriteSQLStatements(filePath);
}
@PropertySource("classpath:application.properties")
@Configuration
public class ExcelReader {

    public static final String SQL_FILE_NAME = "SQL_insert_statements_for_LBU.txt";

    private static final String FILE_PATTERN = ".xlsx";

    private static final String INVALID_VALUE_IN_ROW = "invalid values in row ";
    private static final String INVALID_SOU_CODE = ": length of sou code should be less than 10";
    private static final String INVALID_LOCATION_NUMBER = ": length of location number should be less than 15";
    private static final String INSERT_WHEN_EXIST = "INSERT WHEN EXISTS ";
    private static final String SELECT_ID_FROM_M_S_WHERE_CODE = "(SELECT ID from M_S  WHERE CODE = '";
    private static final String INTO_M_S_LOC = "') THEN INTO M_S_LBU_LOC (LBU_ID, GEO_SCOPE_LOC_NUM) SELECT ";
    private static final String FROM_DUAL = "' from dual;";
    private String codes;
    private String locNumbers;
    private String insertStatement;
    @Value("${filepath}")
    private String filePath;

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    public void readInputFileWriteSQLStatements() throws IOException, InvalidFormatException, IllegalArgumentException {

        File directoryPath = new File(filePath);
        File[] files = directoryPath.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(FILE_PATTERN);
            }
        });

        File file = files[0];
        // Creating a Workbook from an Excel file (.xls or .xlsx)
        Workbook workbook = WorkbookFactory.create(new File(filePath + file.getName()));

        System.out.println("NAME ===" + filePath + file.getName());

        BufferedWriter outStream = new BufferedWriter(new FileWriter(filePath + SQL_FILE_NAME));

        // Getting the sheet at index zero
        Sheet sheet = workbook.getSheetAt(0);
        int totalRows = sheet.getPhysicalNumberOfRows();

        //for iterating columns ( 1. & 3. column)
        Row r = sheet.getRow(0);
        int lastColumnUsed = r.getLastCellNum();

        IntStream.range(1, totalRows).forEach(
            iteratedRows - > {

                Row rows = sheet.getRow(iteratedRows);

                IntStream.range(0, lastColumnUsed - 1).forEach(
                    iteratedColumns - > {
                        if (iteratedColumns == 0 || iteratedColumns == 2) {
                            codes = rows.getCell(0).getStringCellValue();

                            //get the location number
                            DataFormatter formatter = new DataFormatter();
                            Cell locNumbers = rows.getCell(2);
                            locationNumbers = formatter.formatCellValue(locNumbers);
                            insertStatement = .....
                        }
                    }

                );

                int lengthCodes = codes.length();
                int lengthLocationNumber = locationNumbers.length();

                try {
                    //the value of location number could be invalid and formatted like "1,000E16" -> 10000000000007800
                    //lenght ist more than 15, so I get the last two chars of location number and check if its less than 15
                    String formatLocationNumbers = locationNumbers.substring(locationNumbers.length() - 2);

                    if (lengthCodes <= 10 && lengthLocationNumber <= 15 && !locationNumbers.contains("+")) {
                        outStream.write(insertStatement);
                        outStream.newLine();
                    }
                    if ((lengthCodes <= 10) &&
                        (locationNumbers.contains("+") && Integer.parseInt(formatLocationNumbers) < 15)) {
                        outStream.write(insertStatement);
                        outStream.newLine();
                    }
                    if ((lengthCodes > 10) && (
                            (locationNumbers.contains("+") && Integer.parseInt(formatLocationNumbers) > 15) ||
                            lengthLocationNumber > 15)) {
                        throw new IllegalArgumentException(INVALID_VALUE_IN_ROW + iteratedRows +
                            INVALID_SOU_CODE +
                            INVALID_LOCATION_NUMBER);
                    }
                    if (lengthCodes > 10) {

                        throw new IllegalArgumentException(INVALID_VALUE_IN_ROW + iteratedRows +
                            INVALID_SOU_CODE);
                    }
                    if ((lengthLocationNumber > 15) ||
                        (locationNumbers.contains("+") && Integer.parseInt(formatLocationNumbers) >= 15)) {
                        throw new IllegalArgumentException(INVALID_VALUE_IN_ROW + iteratedRows +
                            INVALID_LOCATION_NUMBER);
                    }

                } catch (IllegalArgumentException e) {
                    System.out.println(e.getMessage());
                } catch (IOException e) {
                    e.printStackTrace();
                }


            });

        workbook.close();
        outStream.flush();
    }
}

最佳答案

您想重新(设计)或重新(构建)您的实现。

  1. 我会探索 Spring Batch 方法,看看它是否适合您的用例。我看到在这种情况下,Reader (Excel Reader)、Processor 和 Writer (Database Writer) 完全正常工作。

  2. Spring Batch 已经有了单元测试方法。可以关注https://docs.spring.io/spring-batch/4.0.x/reference/html/testing.html

  3. 如果您不想利用 Spring Batch,我建议您将 Reader 和 Processor 以及 Writer 的逻辑与接口(interface)和实现分开,这样您就可以拥有更好的设计和单元测试

希望对您有所帮助。

关于java - 如何通过读取文件并将其写入另一个文件来为我的类(class)编写单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57869798/

相关文章:

java - 如何使用 Selenium Webdriver + Java 确定 Web 元素的输入类型?

java - Eclipse:使用里面的类更改现有包的名称

Spring MVC 与 JAXB,基于通用类的列表响应

java - 按配置文件使用 yaml 属性进行 Spring Boot 测试

java - 如何使用 Java 代码刷新文件夹?

java - 如何强制在 Maven 测试目标期间运行的 testNG 测试超时?

java - Spring:实际请求参数不满足参数条件 "loanTitle"

mysql - 插入多行 JPA Spring Boot Mysql

testing - 在多种语言上运行相同的测试套件(本地化)

node.js - Mocha + Chai - 没有关于错误的详细信息