1

我正在开发一个用于构建 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格式。我将如何测试这个?我不知道从哪里开始。

4

1 回答 1

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 对象。正如我的第一个规范所示,您只想能够干净地访问属性。

于 2014-02-15T10:50:00.903 回答