Пробный возврат цепного метода со споком - PullRequest
0 голосов
/ 28 апреля 2018

Я застрял на этом немного. Можно ли смоделировать новый URL (url) .openStream (), чтобы вернуть файл .gz? Я использую спок, чтобы попытаться сделать это.

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 Ответ

0 голосов
/ 29 апреля 2018

Проблема с тестируемостью почти всегда одна и та же: без внедрения зависимостей. Этот случай ничем не отличается. Здесь конкретная проблема заключается в том, что вы не можете просто предоставить URL-адрес file://..., потому что вы используете Apache Commons Validate, который выдает false для isValid(url).

Решение состоит в том, чтобы позволить вашему классу внедрить UrlValidator через установщик или дополнительный конструктор. Я выбираю подход сеттера в моем примере кода. Я даже сделал сеттер с областью действия пакета, если вам не нравится общедоступный сеттер, поэтому вы можете просто поместить свой тест в тот же пакет, что и исходный класс (что в любом случае является обычной практикой), чтобы получить к нему доступ.

Теперь просто вставьте макет во время теста и с радостью используйте 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, это запах кода, и вы должны рефакторинг, что я и сделал для вас.

...