踩坑背景
我遇到的這個問題,在 windows 平台上,測試用例運行正常,但是到了 linux 平台上構建時,測試用例總是運行失敗!
而且因為自動構建又不能打斷點,所以只好一點點地分析問題所在!
我的需求是這樣的:
-
首先,在 src/test/resources 文件夾下面創建 xxxx.txt 文件
-
接着,從 xxxx.txt 文件中讀取字符串
-
最后,把字符串按行分割,並且過濾掉一些不需要的行(比如注釋行)
但是郁悶的是,我在 windows 上隨機選擇的一行數據總是我期望的,但是在 linux 平台上隨機選擇的一行總是空字符串
從測試資源文件中讀取字符串
protected String getContentFromResource(String filePath) throws IOException, URISyntaxException {
URL resource = Thread.currentThread().getContextClassLoader().getResource(filePath);
URI uri = resource.toURI();
byte[] bytes = Files.readAllBytes(Paths.get(uri));
String result = new String(bytes, StandardCharsets.UTF_8);
log.info("Get content from resource is {} blank: {}",
StringUtils.isNotBlank(result) ? "not" : "", uri.getPath());
return result;
}
protected int randomInRange(int low, int high) {
return ThreadLocalRandom.current().nextInt(low, high);
}
一開始總懷疑是讀取不到數據,但是嘗試多次后發現,在 linux 系統上測試用例是可以正常讀取到文件中的數據!
隨機選取一行
protected String randomLine(String lines, Predicate<String> predicate) {
List<String> validLines = Arrays.stream(lines.split("\r\n"))
.filter(predicate).collect(Collectors.toList());
if (validLines.size() == 0) {
return "";
}
int index = randomInRange(0, validLines.size());
if (index < validLines.size()) {
return validLines.get(index);
} else {
return "";
}
}
找了好久才發現問題就出在 lines.split("\r\n")
。txt文件在 windows 平台上行尾是 \r\n
, 但是到了 linux 平台上,行尾卻是 \n
。
同樣是對從 txt 文件中讀取到字符串調用 split("\r\n")
,結果在 linux 平台上總是只得到一行,但在 windows 平台上卻是正常的多行!
解決方案
/**
* 讀取多行數據的問題。
*
* @param lines 多行數據字符串
* @return 分割后的多行
*/
protected List<String> readLines(String lines) {
List<String> result = new LinkedList<>();
try (StringReader reader = new StringReader(lines);
BufferedReader buffer = new BufferedReader(reader)) {
String line;
// 按行讀取字符串
while ((line = buffer.readLine()) != null) {
result.add(line);
}
} catch (IOException e) {
log.error("IO Exception occurred.", e);
}
return result;
}
然后再把 Arrays.stream(lines.split("\r\n"))
替換成 readLines(lines).stream()
修改后的 randomLine 代碼如下:
protected String randomLine(String lines, Predicate<String> predicate) {
List<String> validLines = readLines(lines).stream()
.filter(predicate).collect(Collectors.toList());
if (validLines.size() == 0) {
return "";
}
int index = randomInRange(0, validLines.size());
if (index < validLines.size()) {
return validLines.get(index);
} else {
return "";
}
}