我有这个方法:
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下载文件并以块的形式写入下载的文件。
我想知道如何对它进行单元测试,模拟实际的请求。由于它通过某些块使用分块,因此有点复杂。
我以前有这个代码:
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
所以我想知道如何对相同类型的东西进行单元测试...即在模拟Typhoeus的同时创建路径,保存文件等。由于它是第三方库,我不需要测试它是否有效,只是它被正确调用。
这是分块,on_body
和on_complete
令我感到困惑(就如何测试而言)
答案 0 :(得分:3)
您的方法的主要职责是将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
之后,您的测试将不会创建任何本地文件,但功能将保持不变。
答案 1 :(得分: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
电话的抄写和嘲笑,因为这些很容易。
这个问题的有趣部分是如何在RSpec中存储这样的API,这就是我所说的。但是,我可能会首先编写一个验收测试(Cucumber或RSpec功能规范),它首先执行所有代码,然后编写单元测试以测试错误处理等。