我需要读取 xlsx 文件并将输出与 SQL 语句结合写入文件。
要求如下:
- 文件位于 C 盘的特定文件夹中。
- 在文件中,第一列和第三列应该没有标题。
- 一个 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();
}
}
最佳答案
您想重新(设计)或重新(构建)您的实现。
我会探索 Spring Batch 方法,看看它是否适合您的用例。我看到在这种情况下,Reader (Excel Reader)、Processor 和 Writer (Database Writer) 完全正常工作。
Spring Batch 已经有了单元测试方法。可以关注https://docs.spring.io/spring-batch/4.0.x/reference/html/testing.html
如果您不想利用 Spring Batch,我建议您将 Reader 和 Processor 以及 Writer 的逻辑与接口(interface)和实现分开,这样您就可以拥有更好的设计和单元测试
希望对您有所帮助。
关于java - 如何通过读取文件并将其写入另一个文件来为我的类(class)编写单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57869798/