我需要在抽象类中使用Junit
测试一些异常。
抽象类:
public abstract class AbstractReport {
private final Log logger = LogFactory.getLog(this.getClass());
private static final String PREFIX_NAME = "reportFile";
protected Path generate(String templatePath, Map<String, Object> params, JRDataSource datasource) {
// Temporal file to write the document
Path file = null;
try {
file = Files.createTempFile(PREFIX_NAME, null);
} catch (final IOException e) {
logger.error("Exception creating temp file",e);
return null;
}
try (InputStream reportStream = this.getClass().getResourceAsStream(templatePath); FileOutputStream outputStream = new FileOutputStream(file.toFile())) {
final JasperDesign jd = JRXmlLoader.load(reportStream);
final JasperReport jr = JasperCompileManager.compileReport(jd);
final JasperPrint jp = JasperFillManager.fillReport(jr, params, datasource);
final JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(Arrays.asList(jp)));
final SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
exporter.setConfiguration(configuration);
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream));
exporter.exportReport();
} catch (final JRException e) {
logger.error("Exception processing report",e);
file.toFile().delete();
return null;
} catch (final FileNotFoundException e) {
logger.error("Report template not found",e);
file.toFile().delete();
return null;
} catch (final IOException e) {
logger.error("Exception reading report template",e);
file.toFile().delete();
return null;
}
return file;
}
}
我需要测试此代码中的每个catch。研究我发现使用 Mockito 你可以在调用方法时模拟异常,所以例如我可以在调用“generate”时触发异常,但是,我不知道如何在内部触发异常我的“生成”代码(例如创建临时文件时的IOException
)。
答案 0 :(得分:1)
我认为在您的情况下,静态方法调用会抛出异常。 Mockito无法模拟静态方法调用,因为它被认为是糟糕的设计。
如果您不想重构代码,可以使用PowerMockito
@PrepareForTest({JRXmlLoader.class})
@RunWith(PowerMockRunner.class)
public class ReportTest {
@Test
public void test() {
PowerMockito.mockStatic(JRXmlLoader.class);
when(JRXmlLoader.load(any(InputStream.class))).thenThrow(new IOException());
//call the method of your test class
}
}
这会使方法JRXmlLoader.load
抛出IOException
。以同样的方式,您可以模拟静态方法来抛出其他异常。
您可以参考this docs了解详情。
如果您不想添加额外的依赖项,那么我建议封装静态方法的调用:
class JaspreUtilsProvider {
JasperDesign loadJasperDesign(InputStream reportStream) throws ... {
JRXmlLoader.load(reportStream);
}
//encapsulating other static methods
}
然后将此类作为依赖项传递给AbstractReport
构造函数。现在将静态方法的所有调用更改为此对象的调用
public abstract class AbstractReport {
private final JaspreUtilsProvider jaspreUtilsProvider;
public AbstractReport(JaspreUtilsProvider jaspreUtilsProvider) {
this.jaspreUtilsProvider = jaspreUtilsProvider;
}
protected Path generate(String templatePath, Map<String, Object> params, JRDataSource datasource) {
//.........
final JasperDesign jd = jaspreUtilsProvider.loadJasperDesign(reportStream); // instead of JRXmlLoader.load(reportStream);
//.........
}
}
现在很容易创建JaspreUtilsProvider
的子类,它抛出异常并将其传递给测试类而不是真正的JaspreUtilsProvider
实例。这是最便宜的解决方案。