在我正在进行的项目中,我们使用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忽略了。
那么你有什么建议可以解决这个问题吗?
答案 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的答案是可行的。