2

私はこの方法を持っています:

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 をクリアして再作成し、書き込み用にファイルを開き、@feedURL からファイルをダウンロードし、ダウンロードしたファイルにチャンクで書き込みます。

実際のリクエストを嘲笑して、それを単体テストする方法を考えています。一部のブロックを介してチャンクを使用するため、少し複雑です。

私は以前にこのコードを持っていました:

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_bodyon_completeそれは私を混乱させています(テスト方法に関して)

4

2 に答える 2

4

メソッドの主な役割は、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 はこれに適した gem です。https://github.com/simonc/memfs テストに簡単に追加できます:

before do
  MemFs.activate!
end

after do
  MemFs.deactivate!
end

その後、テストはローカル ファイルを作成しませんが、機能は変わりません。

于 2016-08-03T13:16:19.463 に答える
3

重要なのは、RSpecまたはブロックの実装を与えることができるallowexpectということです。したがって、スタブon_bodyon_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

引数は確認しませんでしたが、withs を追加してそれを行うことができます。また、呼び出しのスタブ化とモック化も省略しましたFileUtils。これらは簡単だからです。

この質問の興味深い部分は、RSpec でこのような API をスタブ化する方法です。ただし、最初にすべてのコードをエンド ツー エンドで実行する受け入れテスト (Cucumber または RSpec 機能仕様) を記述し、次にエラー処理などをテストする単体テストを記述します。

于 2016-08-03T12:40:21.090 に答える