测试速率受限外部API与录像机和RSpec调用 [英] Testing rate-limited external API calls with VCR and RSpec

查看:121
本文介绍了测试速率受限外部API与录像机和RSpec调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Rails项目,我使用 VCR 和RSpec测试对外部REST HTTP交互网络服务,只允许它的每秒一次通话的。

In my Rails project, I'm using VCR and RSpec to test HTTP interactions against an external REST web service that only allows calls to it once per second.

这意味着什么,到目前为止,是我结束了我的运行测试套件,直到它失败,因为从Web服务的呼叫次数超过错误。在这个阶段,虽然,至少有一些磁带被记录下来,所以我只是不断地运行测试套件,直到最后我让他们都记录下来,该套件可以只使用磁带(我的 default_cassette_options = {记录运行:new_episodes } )。这似乎并不像一个最佳的方式做事情,尤其是当我发现我需要在未来经常要重新录制我的磁带,我担心不断的电话可以登陆我与Web服务的黑名单(没有测试服务器,他们有一个我知道的)。

What this means so far is that I end up running my test suite until it fails due to a "number of calls exceeded" error from the web service. At that stage though, at least some cassettes get recorded, so I just continually run the test suite until eventually I get them all recorded and the suite can run using only cassettes (my default_cassette_options = { record: :new_episodes }). This doesn't seem like an optimal way to do things, especially if I find I need to re-record my cassettes in the future often, and I worry that constant calls could land me on a blacklist with the web service (there's no test server they have that I know about).

所以,我最终设法把呼叫在我的Rspec的睡眠(1) 块直接前调用Web服务是由,然后重构这些调用成录像机配置:

So, I ended up trying putting calls to sleep(1) in my Rspec it blocks directly before the call to the web service is made, and then refactored those calls up into the VCR configuration:

规格/支持/ vcr.rb

VCR.configure do |c|
  # ...
  c.after_http_request do |request, response|
    sleep(1)
  end
end

虽然这似乎做工精细,有没有更好的方式来做到这一点?此刻,如果到外部服务的调用不具有一个盒已是该组中的最后的测试,然后该套件不必要休眠1秒。同样地,如果没有磁带在测试套件2 Web服务调用之间的时间比一次秒多,那么还有另一种不必要的停顿。有没有人做出任何形式的逻辑来测试这些种类的情况下,还是有办法优雅地做到这一点在VCR配置?

Although this seems to work fine, is there a better way to do this? At the moment, if a call to an external service that doesn't have a cassette already is the final test in the suite, then the suite sleeps unnecessarily for 1 second. Likewise, if the time between 2 web service calls without cassettes in the test suite is more than once second, then there's another unnecessary pause. Has anyone made any kind of logic to test for these kinds of conditions, or is there a way to elegantly do this in the VCR configuration?

推荐答案

首先,我会建议不要使用:new_episodes 为您的录音模式。它有它的用途,但是默认的(:一旦)通常是你想要的。为准确度,要记录的盒如在单次通过中所做的HTTP请求的序列。随着:new_episodes ,您可以用包含磁带拉闸HTTP用户都相隔几个月,但现在正在回放在一起,真正的HTTP服务器不得以任何回应互动同样的方式。

First off, I would recommend against using :new_episodes as your record mode. It has it's uses, but the default (:once) is generally what you want. For accuracy, you want to record a cassette as a sequence of HTTP requests that were made in a single pass. With :new_episodes, you can wind up with cassettes that contain HTTP interactions that were recorded months apart but are now being played back together, and the real HTTP server may not respond in that same fashion.

其次,我会鼓励你听你的测试暴露出来的痛苦,并想方设法去耦大部分的测试套件从这些HTTP请求。你能找到一种方法,让这个只是测试集中在客户端和终端到终端的验收测试做出要求?如果您缠绕HTTP的东西,在一个简单的界面,它应该很容易替代测试双所有其他的测试,也更容易控制你的投入。

Secondly, I'd encourage you to listen to the pain exposed by your tests, and find ways to decouple most of your test suite from these HTTP requests. Can you find a way to make it so that just the tests focused on the client, and the end-to-end acceptance tests make the requests? If you wrap the HTTP stuff in a simple interface, it should be easy to substitute a test double for all the other tests, and more easily control your inputs.

这是一个长期的修复,虽然。在短期内,你可以调整你的VCR的配置,像这样:

That's a longer term fix, though. In the short term, you can tweak your VCR config like so:

VCR.configure do |vcr|
  allow_next_request_at = nil
  filters = [:real?, lambda { |r| URI(r.uri).host == 'my-throttled-api.com' }]

  vcr.after_http_request(*filters) do |request, response|
    allow_next_request_at = Time.now + 1
  end

  vcr.before_http_request(*filters) do |request|
    if allow_next_request_at && Time.now < allow_next_request_at
      sleep(allow_next_request_at - Time.now)
    end
  end
end

本使用挂钩过滤器(如记录)运行挂钩只有真实的请求向API主机。 allow_next_request_at 是用来睡觉的时间所需的最低金额。

This uses hook filters (as documented) to run the hooks only on real requests to the API host. allow_next_request_at is used to sleep the minimum amount of time necessary.

这篇关于测试速率受限外部API与录像机和RSpec调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆