2017-04-11 46 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"を呼び出すと例外が発生する可能性がありますが、 "generate"コード内で例外を発生させる方法(たとえば、一時ファイルを作成するときはIOException)。

+1

このクラスに依存性がない場合、模擬するものは何もありません。 –

答えて

1

あなたのケースでは、静的メソッド呼び出しによって例外がスローされると思います。 Mockitoは、それが悪い設計とみなされるので、静的メソッド呼び出しを模擬することはできません。 あなたのコードをリファクタリングしたくない場合は、これはIOExceptionをスローする方法JRXmlLoader.loadを行います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 
    } 
} 

を使用することができます。同じ方法で、静的メソッドをモックして、他の例外をスローすることができます。

詳細はthis docsを参照してください。

class JaspreUtilsProvider { 

    JasperDesign loadJasperDesign(InputStream reportStream) throws ... { 
     JRXmlLoader.load(reportStream); 
    } 

    //encapsulating other static methods 
} 

をして、あなたのAbstractReportコンストラクタに依存関係として、このクラスを渡す:あなたは、余分な依存関係を追加したくない場合は

、その後、私はあなたの静的メソッドの呼び出しをカプセル化することをお勧めします。今すぐそれが簡単に例外をスローJaspreUtilsProviderのサブクラスを作成するには、このオブジェクト

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インスタンスのそれをあなたのテストクラスを渡します。これが最も安価な解決策です。

+0

ありがとうSerghey。今私はプロジェクトに余分なライブラリを追加することはできませんので、私は別の解決策を見つける必要があると思います。とにかく、「テストクラスのメソッドを呼び出す」と言う部分で、AbstractReportを継承するMyReportから 'generate'メソッドを呼び出すと、' JRXmlLoader.load'に達するとすぐに例外を発砲する? MyReportは 'JRXmlLoader'(mocked)をどのように注入するのですか? – maqjav

+0

はい、 'JRXmlLoader .load'の呼び出しがあっても、あなたが抽象クラス' PowerMock'で呼び出しが発生したとしても、あなたの呼び出しを模擬することができます。 –

+0

追加の依存関係を追加する場合は、この呼び出しを実行する別のオブジェクトの静的メソッドの呼び出しをカプセル化してください。そして、このオブジェクトを依存関係としてクラスに渡します。 –