2017-04-11 85 views
0

我需要使用Junit抽象類中的一些異常進行測試。抽象類Java中的模擬異常

抽象類:

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; 
    } 
} 

我需要從這個代碼測試每捕獲。研究我發現Mockito你可以在調用方法時模擬異常,所以例如當我調用「generate」時我可以觸發異常,但是,我不知道如何在我的「生成」代碼中觸發異常(例如創建臨時文件時的IOException)。

+1

如果這個類沒有依賴關係,那就沒有什麼可以模擬的。 –

回答

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例如您的測試類。這是最便宜的解決方案。

+0

謝謝Serghey。現在我無法將額外的庫添加到我的項目中,所以我想我將不得不尋找其他解決方案。無論如何,爲了理解它,在你稱之爲「調用你的測試類的方法」的部分,如果我從MyReport調用了方法'generate',它擴展了AbstractReport,一旦它達到'JRXmlLoader.load',它就會引發異常? MyReport如何獲得「JRXmlLoader」(模擬)注入? – maqjav

+0

是的,只要你調用了'JRXmlLoader .load',即使這個調用發生在你的抽象類中'PowerMock'能夠爲你調用這個調用。 –

+0

如果您現在添加額外的依賴關係,那麼您應該在另一個對象中封裝對靜態方法的調用,以便爲您調用此調用。然後將此對象作爲依賴項傳遞給您的類。 –