如何对以文件为参数的方法进行单元测试和模拟



我有一个类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的方法?

让我补充一下@LouisWasserman的回答。

您无法测试依赖于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.FileSystemPath,它们可以交换为测试实现,例如。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——这些都可以被嘲笑。使用工厂隐藏对文件的依赖关系。

相关内容

  • 没有找到相关文章

最新更新