[英]Test for thrown exception in constructor method not behaving as expected
我有以下代码从我试图为其编写单元测试的 csv 文件中读取数据。 我不确定如何与 go 联系。
public class BudgetTags implements BudgetTagsList{
// State variables
private Set<String> tags = new TreeSet<>();
private String tag_file_path;
public BudgetTags(String tag_file_path){
//Retrieve tags from tag file
this.tag_file_path = tag_file_path;
this.retrieveTags();
}
public void retrieveTags() {
String line = "";
try{
// Begin reading each line
BufferedReader br = new BufferedReader(new FileReader(this.tag_file_path ));
while((line = br.readLine()) != null){
String[] row = line.split(",");
this.tags.add(row[0]); //Assume correct file format
}
br.close();
} catch (IOException e){
System.out.println("Fatal exception: "+ e.getMessage());
}
}
}
请注意方法retrieveTags();
不允许我指定额外的FileNotFoundException
因为它扩展了IOException
。 它正在通过以下方式进行测试:
@Test
@DisplayName("File name doesn't exist")
void testRetrieveTag3() {
String path = "test\\no_file.csv";
//Instantiate new tags object
BudgetTags tags = new BudgetTags(path);
IOException thrown = assertThrows(IOException.class, () -> tags.retrieveTags());
}
变量path
不存在,所以我希望测试能够捕获 IOException(尽管我更喜欢 FileNotFoundException)。 当我运行这个特定的测试时,我收到一个AssertionFailedError
我如何重构我的测试,以便它在实例化新标签 object 时捕获 FileNotFoundException,因为在生成新标签 object 时调用 retrieveTags()?
retrieveTags()
方法不允许我指定
您的assertThrows
测试失败,因为构造函数不可能抛出IOException
。 首先,它是一个已检查的异常,这意味着构造函数和方法都需要一个throws IOException
子句。 其次,你捕捉到异常; 它没有被抛出方法。
根据您的测试,它应该看起来更像这样:
public class BudgetTags implements BudgetTagsList {
private final Set<String> tags = new TreeSet<>();
private String tagFilePath;
public BudgetTags(String tagFilePath) throws IOException {
this.tagFilePath = tagFilePath;
retrieveTags(); // can throw IOException
}
public void retrieveTags() throws IOException {
// note: use try-with-resources to handle closing the reader
try (BufferedReader br = new BufferedReader(new FileReader(tagFilePath))) {
String line;
while ((line = br.readLine()) != null) {
String row = line.split(",");
tags.add(row[0]);
}
}
// don't catch the exception; your test indicates you want it
// thrown out to the caller
}
}
class BudgetTagsTests {
@Test
@DisplayName("File does not exist")
void testRetrieveTags3() {
String tagFilePath = "test/no_file.csv";
// note: we need to test on the constructor call, because you call
// 'retrieveTags()' in it.
assertThrows(FileNotFoundException.class, () -> new BudgetTags(tagFilePath));
}
}
通过传递FileNotFoundException.class
,如果抛出任何其他IOException
,测试将失败。
无论如何,您不应该像现在这样捕获IOException
。 是的,您将其记录下来,这意味着如果您查看日志,您会发现出现了问题。 但是其他代码不会知道出了什么问题。 对于该代码,文件中似乎根本就没有标签。 通过将IOException
给retrieveTags()
的调用者,您可以让调用者根据需要对异常做出反应。 如果调用成功,但标签为空,则它知道文件存在但只是没有标签。
另外,你说:
请注意方法
retrieveTags();
不允许我指定额外的FileNotFoundException
因为它扩展了IOException
。
我不确定您从该语句中到底尝试了什么,但是即使您也捕获了更一般的异常,也可以捕获更具体的异常。 只是 catch 块的顺序很重要:
try {
somethingThatThrowsIOException();
} catch (FileNotFoundException ex) {
// do something special for when the file doesn't exist
} catch (IOException ex) {
// handle general exception
}
更具体的异常必须在更一般的异常之前被捕获。
该方法实际上不是抛出异常而是捕获它。 您实际需要测试的是您的 catch 块是否已执行。 如果您捕获异常时只想打印错误, 测试 system.out可以帮助您断言打印语句
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.