当前位置: 首页 > 知识库问答 >
问题:

带spock的链式方法的模拟返回

邢财
2023-03-14

我在这件事上纠结了一段时间。是否可以模拟新URL(URL)。openStream()返回一个文件。广州?我正在使用斯波克来尝试这样做。

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()
}
}

或者我最好编写一个私有方法来返回流?

共有1个答案

申炳
2023-03-14

可测试性的问题几乎总是一样的:没有依赖注入。这种情况也不例外。这里的具体问题是,您不能简单地提供file://...URL,因为您使用Apache Commons Validate,这会为isValid(URL)生成false

解决方案是使您的类能够通过setter或其他构造函数注入UrlValidator。我在示例代码中选择setter方法。如果您不喜欢公共setter,我甚至使setter包范围化,所以您可以将您的测试放入与原始类相同的包中(无论如何这是常见的做法),以便访问它。

现在只需在测试期间注入一个mock并愉快地使用一个文件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()
  }
}

顺便说一句,该测试还显示了如何将从相对路径创建的文件实例转换为文件URL。

注意:您还可以使用PowerMock来模拟静态方法或构造函数,这也可以解决问题。但我相信,无论何时您需要PowerMock,它都是一种代码味道,您应该重构,这就是我为您所做的。

 类似资料:
  • 给定一个类Foo 为什么我用Spock来嘲笑Foo 调用总是返回false? 不确定这是否有区别,但测试是在Groovy/Spock中进行的,而Foo是在Java8中进行的。

  • 所以我想做一些事情 但我得到了空异常

  • 我在spring boot应用程序中用groovy(spock)编写了一个集成测试。其中一个应用程序bean称为,它具有以下方法: 在类中还有其他方法。在我的集成测试中,我只想模拟该特定方法的响应。以以下方式: 我希望进行其他验证,但不是这次。基本上,我想实现这一点,但与斯波克。我想取消执行方法

  • 我试图为一个类编写一个单元测试,这个类使用带有库中的的Google vision API。问题是,由于某种原因,我的模拟仍然调用真正的方法,然后抛出一个NPE,这破坏了我的测试。我以前从未在模拟上见过这种行为,我想知道我是不是做错了什么,是不是Spock/Groovy中有bug,还是与Google lib有关?

  • 如何模拟返回已强制转换的模拟对象的方法。 试验方法。

  • 1)创建groovy项目 2)创建接口: 3)创建spock测试: 有没有更好的方法来“解释”spock被模仿函数的最后一个参数是vararg,因此可以省略它?