测试有问题的行是
String filename = "countriesInEurope.txt";
FileReader fr = new FileReader(filename);
因为
- 文件名是硬编码的,无法替换以进行测试
-
FileReader 使用难以模拟的底层系统 io
尽管如此,还是有一些方法可以让您的代码可测试
1.引入构造函数来参数化ReadFile对象的创建
public class ReadFile {
private String filename;
public ReadFile(String filename) {
this.filename = filename;
}
public List<String> showListOfCourses() throws IOException {
FileReader fr = new FileReader(filename);
...
return courseList;
}
}
然后,在您的测试中,您可以创建一个使用某些测试文件的ReadFile 对象。
使用此策略,您可以实现 100% 的行覆盖率,但您的测试必须访问文件系统上的真实文件。所以你不能把它写成一个纯粹的单元测试。
2。将有问题的行提取到可覆盖的方法中
public class ReadFile {
public List<String> showListOfCourses() throws IOException {
Reader courcesReader = openCoursesFile();
BufferedReader br = new BufferedReader(courcesReader);
List<String> courseList = new ArrayList<>();
// ...
return courseList;
}
protected Reader openCoursesFile() throws FileNotFoundException {
return new FileReader("countriesInEurope.txt");
}
}
在您的测试中,您可以继承 ReadFile 类并覆盖 Reader openCoursesFile() 方法。例如
@Test
public void showCources() throws IOException {
ReadFile readFile = new ReadFile() {
protected Reader openCoursesFile() throws java.io.FileNotFoundException {
return new StringReader("Germany\nItaly\nFrance");
};
};
List<String> showListOfCourses = readFile.showListOfCourses();
Assert.assertEquals(Arrays.asList("Germany", "Italy", "France"), showListOfCourses);
}
使用此策略,您可以将测试编写为纯单元测试,因为您将文件访问替换为StringReader(仅在内存中)。唯一无法测试的行是
return new FileReader("countriesInEurope.txt");
所以没有 100% 的线路覆盖率。
编辑
3.引入一个构造函数并传递给它一个Reader对象创建
public class ShowListOfCoursesReader {
private Reader reader;
public ReadFile(Reader reader) {
this.reader = reader;
}
public List<String> read() throws IOException {
// read with reader and transform each line to the
// output object.
// In your case just the line you read, but it could
// also be a date or a address object
...
return courseList;
}
}
然后,在您的测试中,您可以创建一个使用传递的阅读器的ShowListOfCoursesReader 对象。读者也可以是StringReader。
使用此策略,您可以实现 100% 的线路覆盖率和纯单元测试。