在这种情况下,我如何使用VCR(使用WebMock)?

时间:2014-02-14 16:44:33

标签: ruby api rspec vcr webmock

我正在开发用于构建API包装器的DSL,名为Hendrix。我在测试DSL方面遇到了问题。由于它是一个API包装器,因此需要与外部服务进行交互。我不确定如何在测试方面做到这一点。我正在使用RSpec并尝试使用WebMock配置VCR,但没有运气。如果我无法直接访问正在发出的请求,我该如何测试这种特定情况呢?

这是我的spec_helper.rb

$VERBOSE = nil

require 'simplecov'
require 'coveralls'

SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
  SimpleCov::Formatter::HTMLFormatter,
  Coveralls::SimpleCov::Formatter
]
SimpleCov.start { add_filter '/spec/' }

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'hendrix'

require 'vcr'

VCR.configure do |c|
  c.cassette_library_dir = 'spec/cassettes'
  c.hook_into :webmock
end

RSpec.configure do |config|
  config.treat_symbols_as_metadata_keys_with_true_values = true
  config.run_all_when_everything_filtered = true
  config.filter_run :focus
  config.order = 'random'
  config.extend VCR::RSpec::Macros
end

该项目尚处于初期阶段(目前正朝着0.1.0版本努力)。 DSL的语法如下:

require 'hendrix'

Hendrix.build 'Jimi' do
  base 'https://api.github.com'

  client :issues do
    action :issue, '/repos/:owner/:repo/issues/:number'
  end
end

Jimi.issue('rafalchmiel', 'hendrix', 1)
  # => {"url"=>"https://api.github.com/repos/rafalchmiel/hendrix/issues/1",
  #  "labels_url"=> ...
Jimi.issue('rafalchmiel', 'hendrix', 1).title
  # => "Implement parameters in actions"

在大多数规范中,我正在测试主模块(在本例中为Jimi.issue等)中的方法返回的内容以及它是否为Hashie::Mash格式。我该如何测试?我不知道从哪里开始。

1 个答案:

答案 0 :(得分:4)

对于集成测试,我通常直接使用webmock存根端点,而不尝试记录实际请求。这意味着您可以在同一个地方控制响应和期望。您可以对库是否正确解析响应有所期望,并且可以编写测试来验证请求是否已正确完成。浏览gem的每个功能以获取功能列表。这是一个例子:

require "webmock/rspec"

describe "parsing results" do

  let(:url) { "http://..." }

  it "parses results into nice methods" do
    stub_request(:get, url)
      .to_return(
        body: { title: "implement" }.to_json,
        headers: { content_type: "application/json" },
      )

    perform_request
    expect(response.title).to eq "implement"
  end

  it "sends the user agent header correctly" do
    stub_request(:get, url)
    perform_request
    expect(a_request(:get, url).with(
      headers: { user_agent: "hendrix" }
    )).to have_been_made.once
  end

  it "interpolates values in URLs"

  it "supports DELETE requests"

  it "supports HTTP Basic"

  def perform_request
    # ...
  end

end

尽量不记录真实的请求:使用真实的Web服务器很难控制正确的环境,特别是如果你不是编写规范的人。特别是当你写这样的通用库时。如果你想访问一个特定的服务器并且你的代码真的依赖于那个服务器,那么VCR很不错。

也不要检查类型。我现在在你的宝石中看到了很多东西。没有人关心你是否返回一个Hashie :: Mash对象。正如我的第一个规范所示,您只是希望能够干净地访问这些属性。

相关问题