Java 使用Mockito/PowerMockito在没有现有文件的情况下模拟FileInputStream

Java 使用Mockito/PowerMockito在没有现有文件的情况下模拟FileInputStream,java,junit,mockito,powermockito,Java,Junit,Mockito,Powermockito,我正在为使用FileInputStream的方法编写JUnit,并且在构造函数中只传递文件名。该文件是作为servlet请求的一部分创建的,并且该文件不会存储在任何位置 我正在尝试使用PowerMockito模拟FileInputStream,以便它给我一个模拟文件对象。不幸的是,我得到了有效的FileNotFoundException,但我不确定如何测试该方法,因为该文件不存在 试验方法: public String viewReport() throws Exception { th

我正在为使用
FileInputStream
的方法编写
JUnit
,并且在
构造函数中只传递文件名。该文件是作为servlet请求的一部分创建的,并且该文件不会存储在任何位置

我正在尝试使用
PowerMockito
模拟
FileInputStream
,以便它给我一个模拟文件对象。不幸的是,我得到了有效的
FileNotFoundException
,但我不确定如何测试该方法,因为该文件不存在

试验方法:

public String viewReport() throws Exception {
    this.inputStream = new FileInputStream(DOCUSIGN_REPORT_FILE);

    try {
        boolean returnReport = validateRequest();
        if (returnReport) {
            intgList = this.generateViewIntegrationReportData(getESignUIConfig());
            this.createCSVFile(intgList, new FileWriter(DOCUSIGN_REPORT_FILE));
        } else {
            failureResponse(msgs, 400);
            return null;
        }
    } catch (Exception e) {
        e.printStackTrace();
        msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR, 
                    UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
        failureResponse(msgs, 500);
        return null;
    }

    return UiIntegrationKeyConstants.REPORT_REPSONSE;
} 
JUnit测试到目前为止

@Test
public void testViewReport() throws Exception {
    Map<String, Object> actionMap = new HashMap<>();
    actionMap.put("application", "ESignatureIntegrationAction");

    ActionContext.setContext(new ActionContext(actionMap));

    FileInputStream inputStream = Mockito.mock(FileInputStream.class);
    PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(inputStream);

    action = new ESignatureIntegrationAction();
    action.viewReport();
}
@测试
public void testViewReport()引发异常{
Map actionMap=newhashmap();
actionMap.put(“应用程序”、“ESignatureIntegrationAction”);
setContext(新的ActionContext(actionMap));
FileInputStream-inputStream=Mockito.mock(FileInputStream.class);
PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(inputStream);
action=新的ESignatureIntegrationAction();
action.viewReport();
}
当代码到达
新文件inputstream(DOCUSIGN\u REPORT\u文件)时,我得到一个
异常


谢谢您的帮助。

我建议您重构代码,使测试无需模拟框架

它可能看起来有点像这样:

public class YourClass {

    // ...

    public String viewReport()  {
        try {
            boolean isValidRequest = validateRequest();
            if (isValidRequest) {
                IntegrationReportCsvFileHandler fileHandler = new IntegrationReportCsvFileHandler();
                IntegrationReportData inputData = fileHandler.readData(new FileInputStream(DOCUSIGN_REPORT_FILE));

                IntegrationReportGenerator generator = new IntegrationReportGenerator();
                IntegrationReportData outputData = generator.processData(inputData, getESignUIConfig());

                fileHandler.writeReport(outputData, new FileWriter(DOCUSIGN_REPORT_FILE));
            } else {
                failureResponse(msgs, 400);
                return UiIntegrationKeyConstants.FAILURE_RESPONSE;
            }
        } catch (Exception e) {
            e.printStackTrace();
            msgs.add(new Message(ESignatureIntegrationMessageTypeEnum.MESSAGE_TYPE_ERROR, 
                        UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_CODE_500, UiIntegrationKeyConstants.UI_INTEGRATION_ERROR_TEXT_SERVICE_ERROR));
            failureResponse(msgs, 500);
            return UiIntegrationKeyConstants.FAILURE_RESPONSE;
        }

        return UiIntegrationKeyConstants.REPORT_RESPONSE;
    } 

    // ...

}

public class IntegrationReportData {
    // your custom data structure
    // may as well just be a List<Data>
    // may be different for input and output
}

public class IntegrationReportException extends Exception {
    // your custom exception
    public IntegrationReportException(String message) { super(exception); }
}

public class IntegrationReportGenerator {

    public IntegrationReportData processData(IntegrationReportData data, ESignConfig config) throws IntegrationReportException {
        // here's your logic that requires testing
    }

}

public class IntegrationReportCsvFileHandler {

    public IntegrationReportData readData(InputStream input) throws IOException  {
        // read data from given input stream
    }

    public void writeData(IntegrationReportData data, OutputStreamWriter outputWriter) throws IOException {
        // write data to given output stream
    }

}
公共类您的类{
// ...
公共字符串viewReport(){
试一试{
布尔值isValidRequest=validateRequest();
如果(isValidRequest){
IntegrationReportCsvFileHandler fileHandler=新的IntegrationReportCsvFileHandler();
IntegrationReportData inputData=fileHandler.readData(新的FileInputStream(DOCUSIGN_报告_文件));
IntegrationReportGenerator=新的IntegrationReportGenerator();
IntegrationReportData outputData=generator.processData(inputData,getESignUIConfig());
writeReport(outputData,新的FileWriter(DOCUSIGN_REPORT_FILE));
}否则{
故障响应(msgs,400);
返回UiIntegrationKeyConstants.FAILURE\u响应;
}
}捕获(例外e){
e、 printStackTrace();
msgs.add(新消息(ESignatureIntegrationMessageTypeEnum.Message_TYPE_错误,
UiIntegrationKeyConstants.UI_集成_错误_代码_500,UiIntegrationKeyConstants.UI_集成_错误_文本_服务_错误));
故障响应(msgs,500);
返回UiIntegrationKeyConstants.FAILURE\u响应;
}
返回UiIntegrationKeyConstants.REPORT\u响应;
} 
// ...
}
公共类IntegrationReportData{
//您的自定义数据结构
//也可能只是一张清单
//输入和输出可能不同
}
公共类IntegrationReportException扩展了异常{
//您的自定义异常
公共集成报告异常(字符串消息){super(异常);}
}
公共类IntegrationReportGenerator{
公共IntegrationReportData processData(IntegrationReportData数据,ESignConfig配置)引发IntegrationReportException{
//这是需要测试的逻辑
}
}
公共类IntegrationReportCsvFileHandler{
公共集成报告数据读取数据(InputStream输入)引发IOException{
//从给定的输入流读取数据
}
public void writeData(IntegrationReportData数据,OutputStreamWriter outputWriter)引发IOException{
//将数据写入给定的输出流
}
}

这样,
IntegrationReportGenerator
就可以很容易地进行测试。

通常的警告:如果要使用工厂(以及依赖项注入)。。。那么您就不需要Powermock来模拟对new的调用。您的意思是我应该使用Spring注入FileInputStream?如果没有代码可以读取的文件,您的测试实际上会测试什么?所以这个方法是Struts2操作,它将此文件作为CSV文件下载。我知道我无法测试CSV的内容,这就是我试图模拟文件创建部分的原因。这段“代码”中的每一行都是错误设计的尖叫。没有必要对这个函数进行单元测试,因为这样的函数是不存在的。