2014-02-14 34 views
1

我正在開發用於構建API包裝的DSL,名爲Hendrix。我在測試DSL時遇到問題。由於它是一個API包裝器,它需要與外部服務進行交互。我不確定在測試方面如何處理這個問題。我正在使用RSpec並嘗試使用WebMock配置VCR,但沒有運氣。如果我沒有直接訪問正在進行的請求,我該如何測試這個特定的場景?在這種情況下,我將如何使用VCR(與WebMock)?

這是我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

對於集成測試,我通常直接用webmock存根端點,而不嘗試記錄實際的請求。這意味着您可以在同一地點控制響應和期望。您可以對您的庫是否正確解析響應發出期望,並且可以編寫驗證請求是否已正確完成的測試。瀏覽你的寶石的每個功能,以獲得功能列表。這裏有一個例子:

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對象。正如我的第一個規範所顯示的,你只是希望能夠乾淨地訪問屬性。

+0

太棒了,男人!非常感謝;只是我需要的答案。 – raf