1

私が取り組んでいるプロジェクトでは、VCR を使用してローカル サービスと外部サービスの両方のカセットを保管しています。ローカル サービスは常に変更されるマイクロ サービスですが、外部サービスはほとんど変更されません。

この理由に加えて、外部サービスの再録音には長い時間がかかるため、ほとんどの場合、ローカル カセットのみを再録音することは理にかなっています。

それを解決するために、カセットを別のフォルダー (cassettes/localhost とカセット/external/sample.com) に分けようとしました。

次に、次のように考えました。

VCR.configure do |config|
  config.around_http_request do |request|
    host = URI(request.uri).host
    vcr_name = VCR.current_cassette.name
    folder = host
    folder = "external/#{folder}" if host != 'localhost'
    VCR.use_cassette("#{folder}/#{vcr_name}", &request)
  end
  [...]
end

しかし問題は、サーバーが異なる結果を返す場合に、繰り返し要求 (まったく同じ要求) を行う必要があるいくつかのテストがあることです。したがって、上記のコードを使用すると、http 呼び出しごとにカセットがリセットされます。最初のリクエストは記録され、2 番目のリクエストは最初のリクエストの再生です。応答が異なると予想されていた場合でも同様です。

次に、タグとネストされたカセットを使用して別のアプローチを試みました。

RSpec.configure do |config|
  config.around(:each) do |spec|
    name = spec.metadata[:full_description]
    VCR.use_cassette "external/#{name}", tag: :external do
      VCR.use_cassette "local/#{name}", tag: :internal do
        spec.call
      end
    end
  end
  [...]
end

VCR.configure do |config|
  config.before_record(:external) do |i|
    i.ignore! if URI(i.request.uri).host == 'localhost'
  end

  config.before_record(:internal) do |i|
    i.ignore! if URI(i.request.uri).host != 'localhost'
  end
  [...]
end

しかし、これもうまくいきません。その結果、すべての localhost リクエストが内部カセットに記録されました。残りの要求は VCR によって無視されました。

それで、これを解決するための提案はありますか?

4

2 に答える 2

1

:match_requests_on 設定の使用を検討したいと思います。こちらのドキュメントをお読みください: https://www.relishapp.com/myronmarston/vcr/v/2-3-0/docs/request-matching

これにより、同じ URL への複数のリクエストを記録できますが、それらを順番に再生できます。

それに加えて、カセットを異なるディレクトリに分割するというあなたの方法はいいと思います。過去に特定のカセットを強制的に再録音するために行ったことの 1 つは、スペックを再実行する前にカセット自体を削除することです。あなたの場合、それらをうまく分離したので、それは簡単なはずです。

その代わりに、またはそれに加えて、ローカル リクエストであることがわかっている場合は :all レコード設定を使用し、それを configure ブロックにパッチすることができます。何かのようなもの:

VCR.configure do |config|
  config.around_http_request do |request|
    host = URI(request.uri).host
    vcr_name = VCR.current_cassette.name
    folder = host
    if host != 'localhost'
      folder = "external/#{folder}"
      record_mode = :once
    else
      record_mode = :all
    end
    VCR.use_cassette("#{folder}/#{vcr_name}", :record => record_mode, &request)
  end
  [...]
end

私はこれをテストしていないので、もう一度確認してください。もちろん、単に再生したいだけの場合は、:all レコード設定を使用したくないでしょう。テストを呼び出すときに、何らかの方法でスイッチを開発できるかもしれません。

完全な回答ではありませんが、参考になれば幸いです。

于 2012-11-14T18:46:31.517 に答える
1

次に、タグとネストされたカセットを使用して別のアプローチを試みましたが、これもうまくいきません。

ええ、私はこの種のユースケースを念頭に置いてカセットネスティングを設計していません. HTTP インタラクションは常に最も内側のカセットに記録されますが、どのレベルのネストからでも再生できます (最初に最も内側のカセットを試し、次に親チェーンを検索します)。カセットを入れ子にするために私が念頭に置いていた主な使用例はキュウリでした。シナリオ全体に単一のカセットを使用したい場合がありますが、個々のステップ定義に特定のカセットを使用したい場合があります (つまり、そのステップ)。使用中はインナー カセットが「引き継ぎ」ますが、アウター カセットは、インナー カセットが取り出されたときに使用できるように残っています。

これは興味深い使用例ですが... VCR がそのように動作するはずだと思われる場合は、github の問題を開くことを検討してください。さらに議論することができます。

元の質問については、@operandの答えがうまくいくと思います。

于 2012-11-16T23:16:47.843 に答える