书写文件处理函数的时候,最好输入输出写为流文件或者File格式,这样方便mock
File file = new File("abc.txt");
当单元测试读进去之后,只有名字 ”abc.txt" 是存在的,但是后续处理过程中就会报
java.io.FileNotFoundException: xxx.xxx(系统找不到指定文件的异常)
PowerMockito使用时需要引入maven依赖
<dependency> <groupId>org.powermockgroupId> <artifactId>powermock-module-junit4artifactId> <version>2.0.0version> <scope>testscope> dependency> <dependency> <groupId>org.powermockgroupId> <artifactId>powermock-api-mockito2artifactId> <version>2.0.0version> <scope>testscope> dependency>
public class ParserTest {
@Test
public final void testParse() {
File MOCKEDFILE = PowerMockito.mock(File.class);
PowerMockito.when(MOCKEDFILE.exists()).thenReturn(true);
PowerMockito.when(MOCKEDFILE.isFile()).thenReturn(true);
PowerMockito.when(MOCKEDFILE.isDirectory()).thenReturn(false);
PowerMockito.when(MOCKEDFILE.createNewFile()).thenReturn(true);
PowerMockito.when(MOCKEDFILE.length()).thenReturn(11111111L);
//what about the path of MOCKEDFILE which isn't existing
PowerMockito.when(MOCKEDFILE.getPath()).thenReturn(?????);
}
1.FileInputStream流概念
FileInputStream流被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作如读取图片视频等
2.构造方法
2.1 通过打开与File类对象代表的实际文件的链接来创建FileInputStream流对象
public FileInputStream(File file) throws FileNotFoundException{}
若File类对象的所代表的文件不存在;不是文件是目录;或者其他原因不能打开的话,则会抛出
java.io.FileNotFoundException: xxx.xxx(系统找不到指定文件的异常)
2.2 通过指定的字符串参数来创建File类对象,而后再与File对象所代表的实际路径建立链接创建FileInputStream流对象
public FileInputStream(String name) throws FileNotFoundException
实际上源码是先将name转换为file类,然后在读取为FileInputStream对象
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
2.3 通过FileDecscriptor文件描述符来作为参数,文件描述符是指与计算机系统中的文件的连接,前面两个方法的源码中最后都是利用文件描述符来建立连接的(设计计算机系统,暂时不理解)
public FileInputStream(FileDescriptor fdObj)
3.单元测试
当在函数里面用到FileInputStream的时候可以使用
@PrepareForTest(Parser.class)
public class ParserTest {
@Test
public final void testParse() {
File MOCKEDFILE = PowerMockito.mock(File.class);
PowerMockito.when(MOCKEDFILE.exists()).thenReturn(true);
PowerMockito.when(MOCKEDFILE.isFile()).thenReturn(true);
PowerMockito.when(MOCKEDFILE.isDirectory()).thenReturn(false);
PowerMockito.when(MOCKEDFILE.createNewFile()).thenReturn(true);
PowerMockito.when(MOCKEDFILE.length()).thenReturn(11111111L);
//what about the path of MOCKEDFILE which isn't existing
PowerMockito.when(MOCKEDFILE.getPath()).thenReturn(?????);
//how to assign a File an FileInputStream? (I thought something like)
PowerMockito.mockStatic(FileInputStream.class);
FileInputStream MOCKEDINPUTSTREAM = PowerMockito.mock(FileInputStream.class);
PowerMockito.whenNew(FileInputStream.class).withArguments(File.class).thenReturn(MOCKEDINPUTSTREAM);
//how to mock the private method readMyStream
}
@PrepareForTest(Class1.class)是必须的,否则
PowerMockito.whenNew(FileInputStream.class).withArguments(File.class).thenReturn(MOCKEDINPUTSTREAM);
不能代替构造器创建新的FileInputStream。
回答:https://stackoverflow.com/questions/51205275/how-to-mock-fileinputstream-with-powermock
相似的流类型(exp:FileOutputStram,ZipOutputStream之类的都可以使用相同方法来实现)
不过有时候会不起作用,具体原因没找到,改着改着就好了,但不是@PrepareForTest的原因,后续遇到继续总结
示例:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class InputStreamClassDemo {
public void demo1(File file) throws IOException {
FileInputStream fileInputStream = new FileInputStream(file);
byte[] b=new byte[(int) file.length()];
fileInputStream.read(b);
fileInputStream.close();
System.out.println(new String(b));
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import static org.junit.Assert.*;
@RunWith(PowerMockRunner.class)
@PrepareForTest({InputStreamClassDemo.class})
public class InputStreamClassDemoTest {
@InjectMocks
InputStreamClassDemo inputStreamClassDemo;
@Test
public void demo1() throws Exception {
File file = PowerMockito.mock(File.class);
PowerMockito.when(file.length()).thenReturn(3L);
FileInputStream mock = PowerMockito.mock(FileInputStream.class);
PowerMockito.whenNew(FileInputStream.class).withAnyArguments().thenReturn(mock);
inputStreamClassDemo.demo1(file);
}
}