我是单元测试的新手。有一种方法如下:
public Image getImage(String url) {
Document pageSource = fecthSource(url);
Image myImage = parseHtmlToImage(pageSource);
return Image;
}
我写了一个单元测试:
@test
public void getRightPicture() {
Image img = imageFetcher.getImage("http://www.123.com");
assertEquals(img.sourceUrl, "http://www.123.com/456.png");
Image img = imageFetcher.getImage("http://www.abc.com");
assertEquals(img.sourceUrl, "http://www.abc.com/def.png");
}
但是如果访问Internet需要很长时间。我通常想使用本地HTML文件来测试此方法,但有时会测试Web版本。
有什么建议吗?
答案 0 :(得分:3)
您的单元测试无需验证互联网是否正常工作。您应该提供一些模拟HTML文件并指向测试的那些文件。由于您正在处理网址,因此您应该能够指定"file:///path/to/test.html"
之类的路径来代替网址。
答案 1 :(得分:3)
简答:依赖倒置。
更长的答案:
问题可能与fetchSource正在做的事情有关;没有看到细节,这个答案将不得不有点模糊。我假设fetchSource调用实际执行检索的东西,并且这样做的细节并不是你真正感兴趣的测试。我还假设你打算在写“fecht”的任何地方写“fetch”,但这对答案来说并不是特别重要。
你想抽象掉fetchSource的具体内容,这样你就可以专注于测试对你来说重要的东西(parseHtmlToImage?)。有很多方法可以做到这一点:
这是编写可测试代码的一种非常标准的技术(查找依赖性倒置原则)。
答案 2 :(得分:1)
这里有两个选项 -
本地文件肯定是一种更快捷的做事方式;另外,你可以做的是创建一个模拟对象(参见Mockito或Easymock以便于模拟),这样它就可以模拟你要测试的类中的fetchURL方法;
在其他时候,当你想从网上获取URL时 - 由于你正在移开外部的测试依赖项,它在那时变得不仅仅是单元测试了。在这种情况下,您必须处理副作用,即网络延迟,资源可用性等。此集成测试的一个优化是,如果多个测试依赖于它,则缓存资源。这样你每次都不需要通过网络获取。
答案 3 :(得分:1)
要扩展上面的依赖注入答案:
所以你有:
class ImageFetcher {
public Image getImage(String url) {
Document pageSource = fetchSource(url);
Image myImage = parseHtmlToImage(pageSource);
return Image;
}
private Document fetchSource(String url) {
// ... Network IO etc
}
private Image parseHtmlToImage(Document pageSource) {
// Parsing logic
// Network IO
return image;
}
}
第一个问题是“这是否真的属于”ImageFetcher“.IMO fetchSource没有。那(对我来说)听起来像是一个不同的”Web Utils“类会做的事情。我也会提到一个从ImageFetcher到utils类的图像。
class ImageFetcher {
private WebUtils webUtils;
public ImageFetcher(webUtils webUtils) {
this.webUtils = webUtils;
}
public Image getImage(String url) {
Document pageSource = webUtils.fetchSource(url);
Image myImage = parseHtmlToImage(pageSource);
return Image;
}
private Image parseHtmlToImage(Document pageSource) {
imageURL = // Parsing logic
image = webUtils.fetchImage(imageURL);
return image;
}
}
现在Image Fetcher主要关心的是确定要使用哪个图像。它不再需要关心如何从网络获取该图像。可以模拟WebUtils进行单元测试。
@test
public void getImage_ReturnsBannerImage() {
Image expected = // ...
String html = "<html><img src="fred"/>...</html>"; // Keep this short and simple.
mockedWebUtil.fetchSource(Any.String).returns(html);
mockedWebUtil.fetchImage("fred").returns(expected);
var subject = new ImageFetcher(mockedWebUtil);
var actual = subject.getImage("blah");
Assert.AreEqual(expected, actual);
}