Ruby on rails Ruby VCR gem会不断记录相同的请求

Ruby on rails Ruby VCR gem会不断记录相同的请求,ruby-on-rails,ruby,rspec,cucumber,vcr,Ruby On Rails,Ruby,Rspec,Cucumber,Vcr,在我的cucumber支持目录中,我在vcr.rb中有以下内容: require 'vcr' VCR.configure do |c| c.cassette_library_dir = 'fixtures/vcr_cassettes' c.hook_into :webmock c.ignore_localhost = true c.default_cassette_options = { record: :new_episodes } end 我正在对城市名称进行地理编码,以

在我的cucumber支持目录中,我在vcr.rb中有以下内容:

require 'vcr'

VCR.configure do |c|
  c.cassette_library_dir = 'fixtures/vcr_cassettes'
  c.hook_into :webmock
  c.ignore_localhost = true
  c.default_cassette_options = { record: :new_episodes }
end
我正在对城市名称进行地理编码,以调用谷歌地图API。我试图记录并存根这些请求,但它会将相同的请求记录到相同的yml文件中:

- request:
    method: get
    uri: http://maps.googleapis.com/maps/api/geocode/json?address=Miami,%20FL&language=en&sensor=false
    body:
      encoding: US-ASCII
      string: ''
    headers:
      Accept-Encoding:
      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
      Accept:
      - ! '*/*'
      User-Agent:
      - Ruby
  # response...

- request:
    method: get
    uri: http://maps.googleapis.com/maps/api/geocode/json?address=Miami,%20FL&language=en&sensor=false
    body:
      encoding: US-ASCII
      string: ''
    headers:
      Accept-Encoding:
      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
      Accept:
      - ! '*/*'
      User-Agent:
      - Ruby

这是相同的URL和非常相同的请求,VCR不应该存根请求吗?如何防止我的规范在每次尝试搜索同一个城市时都碰到API?

我经历了类似的行为,因此我所做的基本上是保持设置为
:none
。如果出现任何新请求,我将使用
:any
,运行测试套件中执行请求的部分,并将其设置回
:none


似乎是
:new_剧集
使用了一些奇怪的试探法来确定哪些是新请求,哪些是已经发生的请求。在我们的例子中,它将两个不同的支付网关请求标记为相同的请求,导致无休止的调试时间-因为我们得到了
returnOK
CaptureRequest
的响应,诸如此类。最好不要使用
:新的\u剧集

很难说你发布的内容到底是怎么回事,但我可以解释一下VCR是如何工作的,并猜测可能的原因

VCR用于尝试查找以前录制的HTTP交互以播放。在单个磁带会话期间,当播放HTTP交互时,它被视为“已使用”,并且不会再次播放(除非您使用该选项)

所以…我想到了几个可能性:

  • 可能VCR无法匹配您的HTTP请求。您正在使用什么请求匹配器?有一些简单的方法可以解决这个问题(见下文)
  • 如果您没有使用
    :允许播放\u重复
    (这是默认设置,也是我建议您使用VCR的方式),那么您看到的行为可能会在测试中发出多个重复请求时发生,例如。,可能磁带只有一个匹配的请求,但您正在测试其中的两个——这将播放一个并录制一个(因为您使用的是
    :new_剧集
为了解决这个问题,我建议您使用这个选项让VCR打印它正在做什么,以及它试图如何匹配每个请求。这应该会让你了解发生了什么。您还可以覆盖以下任一项,并提供自己的逻辑和/或在matcher中设置断点:

VCR.configure do |c|
  c.register_request_matcher :uri do |request_1, request_2|
    debugger # so you can inspect the requests here
    request_1.uri == request_2.uri
  end
end
您可能也遇到了VCR错误,尽管比较URI(使用
String#=
)是一项非常基本的操作,我很难想象会出现错误。如果您无法解决这个问题,请随时打开github问题(希望是调试记录器输出和/或触发此问题的代码示例)


另一方面,我建议您使用
:once
录制模式(默认),而不是
:new\u剧集
:once
将永远不会将额外的HTTP交互记录到现有磁带上——它只允许磁带记录一次。如果一个请求无法匹配,它将引发一个错误,提醒您它无法匹配<代码>:另一方面,新的\u剧集将记录它找不到匹配的任何请求,这就是您看到的行为。

当我遇到类似问题时,我通过使设置更具体来修复它:

VCR.configure do |c|
    c.default_cassette_options = {
        match_requests_on: [:uri, :body, :method]
    }
end

如果未定义匹配参数,则将Elasticsearch与VCR一起使用将始终重新生成磁带。我必须只将匹配定义为
:method
,因为
:uri
:body
在每次运行测试时都可能发生变化

VCR.configure do |c|
  c.hook_into :webmock
  c.ignore_localhost = true
  c.configure_rspec_metadata!
  c.cassette_library_dir = 'spec/cassettes'
  c.default_cassette_options = { record: :new_episodes,
                                 match_requests_on: [:method] }
end

@埃里克·J——如果有什么人你应该听听,那就是一个叫迈伦的人;)谢谢你,迈伦,我希望你能挺过来;)我刚刚意识到我的回复标题包括
Expires:-Fri,2012年7月13日18:31:50 GMT
,即请求日期后24小时。VCR是否注意到这一点并再次尝试提出请求?如果是的话,有没有办法禁用它?没有,录像机根本不用这个。有一个选项,但它不查看任何头(它只使用配置的间隔),也不会产生您看到的重复交互;它将取代旧的HTTP交互,而不仅仅是添加一个新的。顺便说一句,当我在线时,我会尝试在irc.freenode.net上的#vcr中闲逛,因此如果您需要实时帮助,请随时过来看看。与其使用
:all
:none
切换您提到的内容,我建议使用
:once
录制模式。当磁带已经录制时,它的作用类似于
:none
,或者当磁带是新磁带时,它的作用类似于
:all
。您所指的
:new\u插曲
的“奇怪启发法”只是配置的请求匹配器。它们在所有记录模式下工作相同。
:new_插曲
的效果是,它将记录与以前记录的请求不匹配的请求;相反,
:once
:none
在发生这种情况时将引发错误。