TH's Notes
  • Home
  • Categories
  • Tags
  • Archives

獨立的 API 測試

撰寫測試時, 如果需要透過網路來呼叫外部服務的 API (例如信用卡的交易服務), 因為 API 的回應通常需要一陣子, 這將大幅延長測試所需的等候時間; 此時可以考慮使用 VCR (Video Cassette Recorder) 先將服務的回應記錄下來, 往後當呼叫到此服務的 API 時就自動播放, 以縮短測試時間。

安裝套件

在 Gemfile 中加入

group :test do
  gem 'vcr'
  gem 'webmock'
end

然後執行 bundle install

設定 VCR

在 spec_helper.rb 裡面設定 VCR 如下, 若想了解更多細節可參考 Relish 的文件。

spec/spec_helper.rb:

require 'vcr'

VCR.configure do |c|
  c.cassette_library_dir = 'spec/cassettes'
  c.hook_into :webmock
  c.configure_rspec_metadata!
  c.ignore_localhost = true # 忽略本地端的 request
end

RSpec.configure do |config|

  # 在 RSpec 3 不再需要此行
  config.treat_symbols_as_metadata_keys_with_true_values = true
  ... 程式碼省略 ...
end

加入 :vcr

現在, 只要在測試中加入 :vcr 就會自動記錄 API 的回應, 請參考下面的範例

stripe_wrapper_sepc.rb:

require 'spec_helper'

describe StripeWrapper::Charge do

  let(:token) do
    Stripe::Token.create(
      :card => {
        :number => card_number,
        :exp_month => 1,
        :exp_year => 2016,
        :cvc => "314",
        :description => "some description"
      }
    ).id
  end

  context "with valid card" do
    let(:card_number) { '4242424242424242' }
    it "charges the card successfully", :vcr do # 加入 :vcr
      response = StripeWrapper::Charge.create(amount: 300, card: token)
      expect(response).to be_successful
    end
  end

  context "with invalid card" do
    let(:card_number) { '4000000000000002' }

    it "does not charge the card successfully", :vcr do # 加入 :vcr
      response = StripeWrapper::Charge.create(amount: 300, card: token)
      expect(response).not_to be_successful
    end
    it "contains an error message", :vcr do # 加入 :vcr
      response = StripeWrapper::Charge.create(amount: 300, card: token)
      expect(response.error_message).to be_present
    end
  end
end

請注意,加入 :vcr 後的第一次測試, 仍會呼叫到外部服務,並記錄服務的回應; 之後的測試,才會直接使用先前的記錄。

在 spec/cassettes 裡面可以找到有哪些回應被記錄下來,如下

$ tree spec/cassettes
spec/cassettes
└── StripeWrapper_Charge
    ├── with_invalid_card
    │   ├── contains_an_error_message.yml
    │   └── does_not_charge_the_card_successfully.yml
    └── with_valid_card
        └── charges_the_card_successfully.yml

3 directories, 3 files
Comments
comments powered by Disqus

  • « 在測試中使用 Database Cleaner
  • 在測試中模擬物件行為 »

Published

Jan 26, 2015

Category

Web

Tags

  • rails 63
  • Powered by Pelican. Theme: Elegant by Talha Mansoor