我知道一个好的单元测试永远不应该访问文件系统.所以我也知道,你可以使用Mockito和PowerMock来模拟File类.
但是下面的代码呢:
public ClassLoaderProductDataProvider(ClassLoader classLoader, String tocResourcePath, boolean checkTocModifications) {
// ...
this.cl = classLoader;
tocUrl = cl.getResource(tocResourcePath);
if (tocUrl == null) {
throw new IllegalArgumentException("Can' find table of contents file " + tocResourcePath);
}
this.checkTocModifications = checkTocModifications;
toc = loadToc();
// ...
}
private ReadonlyTableOfContents loadToc() {
InputStream is = null;
Document doc;
try {
is = tocUrl.openStream();
doc = getDocumentBuilder().parse(is);
} catch (Exception e) {
throw new RuntimeException("Error loading table of contents from " + tocUrl.getFile(), e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
try {
Element tocElement = doc.getDocumentElement();
ReadonlyTableOfContents toc = new ReadonlyTableOfContents();
toc.initFromXml(tocElement);
return toc;
} catch (Exception e) {
throw new RuntimeException("Error creating toc from xml.", e);
}
}
Run Code Online (Sandbox Code Playgroud)
该类使用位于tocResource的文件内容初始化它的toc属性.
因此,我想到的第一件事就是创建一个子类,它不会在构造函数中调用super,因此所有文件访问都没有完成.在我自己的构造函数中,然后我插入应该从文件中读取的数据的测试虚拟数据.然后我可以毫无问题地测试其余的课程.
但是,原始类的构造函数代码根本没有测试过.如果有错误怎么办?
事情就是这样:通常,要进行适当的单元测试工作,您需要为类提供接口而不是具体类,以便您可以灵活地执行不同的测试.看看你的例子,在我看来,你应该把负载加载Document到其他类......负责一个叫做的接口DocumentSource.
那么你的代码根本不依赖于文件系统.它可能看起来像
public SomethingProductDataProvider(DocumentSource source, String tocDocumentName,
boolean checkTocModifications) {
this.source = source;
this.tocDocumentName = tocDocumentName;
this.checkTocModifications = checkTocModifications;
this.toc = loadToc();
}
private ReadonlyTableOfContents loadToc() {
Document doc = source.getDocument(tocDocumentName);
if (doc == null) {
throw new IllegalArgumentException("Can' find table of contents file " +
tocResourcePath);
}
try {
Element tocElement = doc.getDocumentElement();
ReadonlyTableOfContents toc = new ReadonlyTableOfContents();
toc.initFromXml(tocElement);
return toc;
} catch (Exception e) {
throw new RuntimeException("Error creating toc from xml.", e);
}
}
Run Code Online (Sandbox Code Playgroud)
或者,您可以让类在其构造函数中直接使用Document或甚至InputStream直接使用.当然,在某些时候你必须拥有InputStream使用ClassLoader... 来加载资源的实际代码......但是你可以将代码推送到只有这样做的简单代码中.然后很明显,你对该类进行的任何测试都必须使用实际文件......但其他类的测试不会受到影响.
作为旁注,如果类在其构造函数中起作用(例如在这种情况下加载目录),那么它对于类的可测试性来说是一个不好的标志.可能有一种更好的方法来设计这里涉及的类,消除了对它的需要,并且更加可测试,但很难确切地说明这个设计是什么.
您还可以使用各种其他选项,包括使用Guava的InputSupplier接口以及已经过测试的工厂方法(如Resources.newInputStreamSupplier(URL))来获取InputSupplier生产中使用的实例.但关键是始终让您的类依赖于接口,以便您可以在测试中轻松使用替代实现.
| 归档时间: |
|
| 查看次数: |
5847 次 |
| 最近记录: |