我有一个类CollectionObject,它创建了一个ArrayList。
public class CollectionObject {
private List<String> collectionObject;
public CollectionObject() {
collectionObject = new ArrayList<String>();
}
public List<String> getCollectionObject() {
return collectionObject;
}
public void add(final String stringToWrite) throws VerifyException {
collectionObject.add(stringToWrite);
}
}
还有另一个类接受类CollectionObject,并使用它将文件的内容写入类CollectionObject。
public class ReaderFileWriterObjectService {
private BufferedReader bufferedReader;
private CollectionObject collectionObject;
private String line;
public CollectionObject getCollectionObjectAfterWritingFromAFile(final File file)
throws VerifyException, IOException {
collectionObject = new CollectionObject();
bufferedReader = new BufferedReader(new FileReader(file));
while ((line = bufferedReader.readLine()) != null) {
collectionObject.add(line);
}
bufferedReader.close();
return collectionObject;
}
如何测试和模拟类ReaderFileWriterObjectService的方法?
您无法测试依赖于java.io.File
的API;这个类不能进行可靠的单元测试(即使它甚至不是JDK级别的final
)。
但新的文件系统API的情况并非如此,它出现在Java7中。
也被称为JSR203,这个API为任何提供"文件系统对象"的存储介质提供统一的API。
短篇小说:
- 一个"文件系统对象"是由这个API中的Path具体化的
- 任何实现JSR203的JDK(即任何Java7+版本)都支持这个API
- 要从默认
FileSystem
上的资源获取路径,可以使用Paths.get()
- 但你并不局限于此
简而言之,在API和测试用例中,应该使用Path
,而不是File
。如果您想测试与某个文件系统资源相关的任何内容,请使用JDK的Files
类来测试Path
实例。
您可以从基于磁盘的主文件系统中创建FileSystem
。建议:使用这个。
我也在做同样的事情,下面的想法正在发挥作用,我希望这对你也有用,
@InjectMocks
private CollectionObject collectionObject;
@Test
public void getCollectionObjectAfterWritingFromAFile() throws Exception {
CollectionObject expectedObject =new CollectionObject();
List<String> expectedList=new ArrayList<String>();
expectedList.add("100");
CollectionObject resultObject =new CollectionObject();
BufferedReader reader=new BufferedReader(new StringReader("100"));
PowerMockito.mock(BufferedReader.class);
PowerMockito.mock(FileReader.class);
PowerMockito.whenNew(FileReader.class).withArguments("test10.csv").thenReturn(null);
PowerMockito.whenNew(BufferedReader.class).withArguments(null).thenReturn(reader);
resultObject=collectionObject.getCollectionObjectAfterWritingFromAFile( "test10.csv");
assertEquals(expectedObject ,resultObject );
}
您可以使用JUnit的TemporaryFolder创建文件,并将资源中的内容复制到其中。
public YourText {
@Rule
public TemporaryFolder folder = new TemporaryFolder();
@Test
public void checkSomething() throws Exception {
InputStream resource = getClass().getResourceAsStream("/your/resource");
File file = folder.newFile();
Files.copy(resource, file);
ReaderFileWriterObjectService service = ...
CollectionObject collection = service
.getCollectionObjectAfterWritingFromAFile(file);
...
}
您不能。你真倒霉。一个更好的设计可以接受Java 7 java.nio.file.FileSystem
和Path
,它们可以交换为测试实现,例如。https://github.com/google/jimfs.
好吧,首先让我们考虑一下你想测试什么?如果是单元测试,那么您不想测试与文件系统通信之类的集成,您必须测试自己的逻辑,您的逻辑如下:1) 使用文件系统集成读取文件中的下一行2) 将此行添加到我的对象中
第二步你不应该测试,因为这种方法太容易破坏。第一步您无法测试,因为它执行集成调用。所以我不认为这里你需要一个单元测试
但如果您的逻辑会更复杂,那么您可以引入接口包装器并在测试中模拟它:
public interface FileWrapper{
public String readLine();
public void close();
}
public class FileWrapperImpl implements FileWrapper{
private File file;
private BufferedReader reader;
public FileWrapperImpl (File file){
this.file = file;
this.reader= ...
}
public String readLine(){
return reader.nextLine();
}
}
然后是您的ReaderFileWriterObjectService:
public CollectionObject getCollectionObjectAfterWritingFromAFile(FileWrapper wrapper)
CollectionObject collectionObject = new CollectionObject();
while ((line = wrapper.readLine()) != null) {
collectionObject.add(line);
}
wrapper.close();
return collectionObject;
}
现在,您可以轻松地模拟FileWrapper进行测试,并将其传递给您的服务
我建议更改API以接受Reader或BufferedReader——这些都可以被嘲笑。使用工厂隐藏对文件的依赖关系。