我一直坚持这一点。是否可以模拟新的URL(url).openStream()来返回file.gz?我正在使用spock尝试这样做。
public class DownloadFile {
public BufferedReader downloadGzipCsvFile(String url) throws MalformedURLException {
BufferedReader br = null;
if (UrlValidator.getInstance().isValid(url)){
try {
br = new BufferedReader(new InputStreamReader(new GZIPInputStream(new URL(url).openStream())));
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
} else{
throw new MalformedURLException("Supplied URL: " + url + " is an invalid URL");
}
return br;
}
}
测试课
class DownloadFileSpec extends Specification{
def "Should return buffered reader for url for gzip csv file"(){
given:
String url = "http://www.test.com"
DownloadFile downloadFile = new DownloadFile()
when:
BufferedReader br = downloadFile.downloadGzipCsvFile(url)
_.openStream() << new FileInputStream("../../../../resources/test_data.csv.gz")
then:
br.ready()
}
}
或者我会更好地编写一个返回流的私有方法吗?
答案 0 :(得分:1)
可测试性的问题几乎总是相同的:没有依赖注入。这种情况也不例外。这里的具体问题是,您不能简单地提供file://...
URL,因为您使用Apache Commons Validate为false
生成isValid(url)
。
解决方案是让您的类通过setter或其他构造函数注入UrlValidator
。我在我的示例代码中选择了setter方法。如果你不喜欢公共的setter,我甚至制作了setter包作用域,所以你可以把你的测试放在与原始类相同的包中(这是常见的做法),以便访问它。
现在只需在测试期间注入一个模拟器,并愉快地使用文件URL:
package de.scrum_master.stackoverflow;
import org.apache.commons.validator.routines.UrlValidator;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.zip.GZIPInputStream;
public class DownloadFile {
private UrlValidator urlValidator = UrlValidator.getInstance();
void setUrlValidator(UrlValidator urlValidator) {
this.urlValidator = urlValidator;
}
public BufferedReader downloadGzipCsvFile(String url) throws MalformedURLException {
BufferedReader br = null;
if (urlValidator.isValid(url)) {
try {
br = new BufferedReader(
new InputStreamReader(
new GZIPInputStream(
new URL(url).openStream()
)
)
);
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
else {
throw new MalformedURLException("Supplied URL: " + url + " is an invalid URL");
}
return br;
}
}
package de.scrum_master.stackoverflow
import org.apache.commons.validator.routines.UrlValidator
import spock.lang.Specification
class DownloadFileSpec extends Specification {
def "Should return buffered reader for url for gzip csv file"() {
given:
String url = new File("src/test/resources/test_data.csv.gz").toURI().toURL()
def downloadFile = new DownloadFile()
downloadFile.urlValidator = Mock(UrlValidator) {
isValid(_) >> true
}
when:
def bufferedReader = downloadFile.downloadGzipCsvFile(url)
then:
bufferedReader.ready()
}
}
顺便说一下,测试还显示了如何将从相对路径创建的File
实例转换为文件URL。
P.S。:您也可以使用PowerMock来模拟静态方法或构造函数,这也可以解决问题。但我相信无论什么时候你需要PowerMock,它都是代码味道,你应该重构,这就是我为你所做的。