如何在主机分割的不同磁带中录制/播放?

时间:2012-11-14 18:00:49

标签: ruby vcr

在我正在进行的项目中,我们使用VCR存储本地和外部服务的磁带。本地的微服务是不断修改的,而外部的服务很难被修改。

由于这个原因以及外部服务需要很长时间才能重新录制,因此我们大部分时间都会重新录制本地录像带。

为了解决这个问题,我们尝试将磁带分离到不同的文件夹中(磁带/ 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调用重置磁带。记录第一个请求,第二个请求是第一个请求的回放,即使响应预计不同。

然后我们尝试使用标签和嵌套磁带的不同方法:

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忽略了。

那么你有什么建议可以解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

我认为您希望使用:match_requests_on设置。阅读此处的文档:https://www.relishapp.com/myronmarston/vcr/v/2-3-0/docs/request-matching

这应该允许您将多个请求记录到同一个URL,但是按顺序重放它们。

除此之外,我认为您将磁带分成不同目录的方法听起来不错。我过去曾做过一件强制重新录制特定磁带的事情,就是在重新运行规格之前删除磁带。在你的情况下应该很容易,因为你很好地分开了它们。

除了或者除此之外,当您知道它是本地请求时,您可以使用:all记录设置,并将其修补到配置块中。类似的东西:

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记录设置。也许你可以在调用测试时以某种方式开发一个开关。

这不是一个完整的答案,但我希望这会有所帮助。

答案 1 :(得分:1)

  

然后我们尝试了一种使用标签和嵌套磁带的不同方法......但这也不起作用。

是的,我没有考虑到这种用例设计卡带嵌套。 HTTP交互始终记录在最里面的盒子中,但可以从任何嵌套级别播放(它首先尝试最里面的盒子,然后向上搜索父链)。我想到的用于嵌套盒式磁带的主要用例是黄瓜:您可能想要在整个场景中使用单个盒式磁带,但是您可能希望使用特定的盒式磁带用于单个步骤定义(即,对于任何使用的场景那一步)。内盒在使用时会“接管”,但是当内盒被弹出时,外盒仍然可用。

这是一个有趣的用例,但是......如果您认为VCR应该以这种方式工作,请考虑为它打开一个github问题,我们可以进一步讨论它。

关于你原来的问题:我认为@operand的答案是可行的。