2016-08-03 6 views
1

У меня есть этот метод:Как насмехаться с RSpec API, который принимает и затем вызывает обратные вызовы блоков?

def download_zip_file 
    FileUtils.rm_rf(@zip_path) if @zip_path 
    FileUtils.mkdir_p(@zip_path) 
    downloaded_file = File.open(@zip_file, "wb") 
    request = Typhoeus::Request.new(@feed, followlocation: true) 
    request.on_body { |chunk| downloaded_file.write(chunk) } 
    request.on_complete { |response| downloaded_file.close } 
    request.run 
end 

Он очищает zip_path, воссоздает его, открывает файл для записи, а затем загружает файл из @feed URL и запись скачанного файла в кусках.

Мне интересно, как выполнить тестирование, издеваясь над фактическим запросом. Поскольку он использует chunking через некоторые блоки, это немного сложно.

Я ранее имел этот код:

def download_feed_data_from_url 
    response = Typhoeus.get(@feed, followlocation: true) 
    raise(FeedNotFoundError, "Could not find feed at feed: #{@feed}. Response: #{response.inspect}") unless response.success? 
    result = response.body 
end 

Что было легко проверить (насмехаясь над Typhoeus и предоставление заглушки возврата):

context "testing feed downloading" do 
    let(:feed) { "http://the.feed.url" } 
    let(:response) { double(body: "some content", success?: true) } 

    before 
    allow(Typhoeus).to receive(:get).with(feed, followlocation:true).and_return(response) 
    end 

    # ... individual assertions, i.e. that Typhoeus is called, that it pulls the body content, etc. 
end 

Так мне интересно, как модульного тестирования такие же вещи ... т. е. что путь создан, файл сохраняется и т. д., в то время как насмешливый Тифой. Поскольку это сторонняя библиотека, мне не нужно проверять, что она работает, просто она называется правильно.

Это CHUNKING и on_body и on_complete что путает меня (в плане того, как проверить его)

ответ

2

Ключ в том, что you can give an RSpec allow or expect a block implementation. Так незавершенная on_body и on_complete, чтобы сохранить блоки вы даете им, и run называть эти блоки:

it "writes to and closes the file" do 
    downloaded_file = double 
    expect(downloaded_file).to receive(:write) 
    expect(downloaded_file).to receive(:close) 
    allow(File).to receive(:open).and_return(downloaded_file) 

    request = double 
    allow(request).to receive(:on_body) { |&block| @on_body = block } 
    allow(request).to receive(:on_complete) { |&block| @on_complete = block } 
    allow(request).to receive(:run) do 
    @on_body.call "chunk" 
    @on_complete.call nil 
    end 
    allow(Typhoeus::Request).to receive(:new).and_return(request) 

    download_zip_file 
end 

Я не проверял никаких аргументов, но вы можете добавить with с, чтобы сделать это. Я также отказался от прослушивания и издевательств над вызовами FileUtils, так как это легко.

Интересная часть этого вопроса заключается в том, как заглушить API, подобный этому, в RSpec, поэтому я обратился к этому вопросу. Тем не менее, я бы, вероятно, написал приемочный тест (спецификация функций огурца или RSpec), вначале который выполняет весь код до конца, а затем записывает модульные тесты для проверки обработки ошибок и т. Д.

+0

Спасибо, Дейв! Да, для меня это было не столько тестирование кода, а скорее понимание того, как тестировать Typhoeus API для chunking. Ваш пример выглядит идеально. Благодаря! –

2

Основная ответственность вашего метода - загрузка zip-файла в определенную папку в локальной файловой системе. Неважно, как вы можете это сделать. Результат здесь имеет значение.

Если вы хотите проверить, правильно ли загружен ваш метод, тогда вы должны заглушить сетевой запрос, затем вызовите метод download_zip_file, а затем проверьте, был ли файл создан по соответствующему пути, и его содержимое соответствует обрезаемому телу ответа.

Typhoeus имеет поддержку запроса: https://github.com/typhoeus/typhoeus/tree/d9e6dce92a04754a2276c94393dad0f3a5c06bdd#direct-stubbing В качестве альтернативы вы можете использовать Webmock для этой же цели. Он имеет поддержку Typhoeus запросов гася: https://github.com/bblimke/webmock

Пример:

it "downloads file" do 
    zip_path = "tmp/downloads" 
    zip_file = "filename.zip" 
    downloaded_file_path = "#{zip_path}/#{zip_file}" 
    feed = "http://www.colorado.edu/conflict/peace/download/peace.zip" 
    zip_file_content = "some zip file content" 

    response = Typhoeus::Response.new(code: 200, body: zip_file_content) 
    Typhoeus.stub(feed).and_return(response) 

    Downloader.new(zip_path, zip_file, feed).download_zip_file 

    expect(File.exists?(downloaded_file_path)).to eq(true) 
    expect(File.read(downloaded_file_path)).to eq(zip_file_content) 
end 

Кроме того, я хотел бы предложить использовать поддельную файловую систему в памяти для тестов, которые создают файлы и папки, для того, чтобы не загрязнять локальная файловая система с мусором. Memfs - хороший камень для этого.https://github.com/simonc/memfs Это легко добавить их к тестам:

before do 
    MemFs.activate! 
end 

after do 
    MemFs.deactivate! 
end 

После того, что тесты не будут создавать локальные файлы, но функциональные возможности останутся прежними.

+0

SunnyMagadan, большое вам спасибо! Я почему-то не видел, чтобы запрос Typhoeus прерывался ... главным образом потому, что у него нет конкретного примера для вызова «загрузка-в-куски» ... но я вижу, как он будет работать с этим (плюс ваш пример). Очень хороший материал. Я также видел библиотеку webmock, но имел ту же проблему (я не видел, как использовать ее с чередованием Typhoeus). О, а также: большое спасибо за предложение memfs. Я просто собирался выполнить ручную очистку fs после тестов, но это намного лучше. Хороший звонок! –

+0

Добро пожаловать. :) – SunnyMagadan

 Смежные вопросы

  • Нет связанных вопросов^_^