Java 编写Junit测试以覆盖异常和捕获块
我已经为以下函数编写了Junit测试用例。当检查JACOCO测试覆盖率时。它显示测试用例只覆盖了try块。我是编写测试用例的新手。如何在测试用例中涵盖异常和catch块 这里有一个方法Java 编写Junit测试以覆盖异常和捕获块,java,spring,unit-testing,junit,junit4,Java,Spring,Unit Testing,Junit,Junit4,我已经为以下函数编写了Junit测试用例。当检查JACOCO测试覆盖率时。它显示测试用例只覆盖了try块。我是编写测试用例的新手。如何在测试用例中涵盖异常和catch块 这里有一个方法 public static List<Student> readCsvFile(String fileName) { BufferedReader fileReader = null; //logic to read file } catch (Exception
public static List<Student> readCsvFile(String fileName)
{
BufferedReader fileReader = null;
//logic to read file
}
catch (Exception e)
{
System.out.println("Error in CsvFileReader !!!");
e.printStackTrace();
} finally
{
try
{
fileReader.close();
} catch (IOException e)
{
System.out.println("Error while closing fileReader !!!");
e.printStackTrace();
}
}
return students;
}
公共静态列表readCsvFile(字符串文件名)
{
BufferedReader fileReader=null;
//读取文件的逻辑
}
捕获(例外e)
{
System.out.println(“CsvFileReader中的错误!!!”;
e、 printStackTrace();
}最后
{
尝试
{
fileReader.close();
}捕获(IOE异常)
{
System.out.println(“关闭文件读取器时出错!!!”;
e、 printStackTrace();
}
}
留学生;
}
测试方法
@Test
public void ReadCsvFileTest()
{
String fileName = "test.csv";
List<Student> result = new ArrayList<Student>();
result = CsvFileReader.readCsvFile(fileName);
Student student1 = null;
Iterator<Student> it = result.iterator();
while (it.hasNext())
{
Student s = it.next();
if ("471908US".equals(s.getId()))
{
student1 = s;
break;
}
}
assertTrue(student1 != null);
}
@测试
public void ReadCsvFileTest()
{
字符串fileName=“test.csv”;
列表结果=新建ArrayList();
结果=CsvFileReader.readCsvFile(文件名);
student1=null;
迭代器it=result.Iterator();
while(it.hasNext())
{
学生s=it.next();
如果(“471908US”.equals(s.getId()))
{
学生1=s;
打破
}
}
assertTrue(student1!=null);
}
考虑到被测方法的当前签名,实现完全覆盖并不容易:只有在try块中抛出异常时,才会执行catch块
解决这个问题的一种方法是:不要传入文件名,而是传入读卡器对象本身。比如:
public static List<Student> readCsvFile(String fileName) {
return readCsvFile(new BufferedReader(fileName));
}
static List<Student> readCsvFile(BufferedReader reader) {
try {
...
} catch( ...
公共静态列表readCsvFile(字符串文件名){
返回readCsvFile(新的BufferedReader(文件名));
}
静态列表readCsvFile(BufferedReader读取器){
试一试{
...
}捕获(。。。
现在,您可以为第二种方法编写几个特定的单元测试。您可以保留只进行“正确”读取的测试;但是您可以添加一个测试,在其中传入一个模拟的reader对象…这只是在某个点上引发一个异常。请注意,我使该新方法仅受包保护-您可能不想使用该“public”;将其私有化将防止其进行单元测试
这将帮助您实现完全覆盖。当然,您还需要至少一个测试来“覆盖”字符串提取方法
一些注意事项:
在这样的情况下,你可能经常考虑向你的类引入额外的依赖关系。下面是一个粗略的例子。为读者创建一个工厂:
interface BufferedReaderFactory
{
public BufferedReader createBufferedReader(String fileName) throws IOException;
}
然后,您将有一个几乎不需要任何测试的简单实现,例如类似的东西:
class BufferedReaderFactoryImpl implements BufferedReaderFactory
{
@Override
public BufferedReader createBufferedReader(String fileName) throws IOException
{
return new BufferedReader(new FileReader(fileName));
}
}
然后,您必须找到一种方法将此依赖项注入到类中。我通常在日常工作中使用,但您可以尝试一些简单的方法,例如使用构造函数注入并使方法非静态。以下是一个示例:
class CsvFileReader
{
private final BufferedReaderFactory factory;
public CsvFileReader(BufferedReaderFactory factory)
{
this.factory = factory;
}
public List<Student> readCsvFile(String fileName)
{
BufferedReader fileReader = null;
try
{
fileReader = factory.createBufferedReader(fileName);
...
}
catch(IOException e)
{
...
}
finally
{
...
}
return new LinkedList<>();
}
}
当然,您可以在没有Mockito的情况下通过实现一个测试工厂来实现这一点。但是这更麻烦,尤其是在更复杂的用例中。一旦抛出IOException
,您将获得JaCoCo提供的适当的覆盖率报告
还要注意JaCoCo的一个限制,在第节中,有异常的源代码行不显示覆盖率。为什么?只有在抛出异常时,才会获得异常块的覆盖率。
CsvFileReader.readCsvFile(“notexisting.csv”)
应该输入catchAs Compass建议您在测试执行期间必须在try块内抛出异常。通常我会使用类似Mockito的模拟框架来实现此目的。但在您的情况下,可能传递无效文件名就足够了。
@RunWith(MockitoJUnitRunner.class)
public class MyTest
{
@Mock
private BufferedReaderFactory mockFactroy;
@Test
public void testIOException() throws IOException
{
String ivalidFileName = "invalid.txt";
//throw exception in case that invalid file name is passed to the factory
Mockito.when(mockFactroy.createBufferedReader(ivalidFileName)).thenThrow(new IOException("Hello!"));
CsvFileReader csvFileReader = new CsvFileReader(mockFactroy);
//invoke with a factory that throws exceptions
csvFileReader.readCsvFile(ivalidFileName);
//...
//and make a sensible test here, e.g. check that empty list is returned, or proper message is logged, etc.
}
}