5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

VCRでレスポンスをERBで設定する

Posted at

自分がしらなかっただけですが、便利だったので。

VCRは外部へのリクエストを記録し、テスト時に外部リクエスト呼び出しをモックしてれるツールです。
VCR自体はカセット(casset)と呼ばれるフィクスチャを記録/再生する機能が主で、モック自体は
webmock/faradayなどのモックライブラリを内部で使用しています。

vcr/vcr: Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.

例えば、下記のようなstripeのapi実行を伴うようなテストケースをVCR.use_cassetteという
ブロックの中実行すると、指定したパスにレクエスト/レスポンスを記録したymlを保存してくれます。
(そして2回目以降はymlを読んで、リクエストにマッチしたら記録されているレスポンスを返してくれます)

describe CancelOrder do
  it 'updates status of order/history' do
    order = create(:order, :with_payment, :fixed)

    VCR.use_cassette 'stripe/refund' do
      CancelOrder.new(order).execute
      # charge = Stripe::Charge.retrieve(order.payment.id)
      # charge.refund
    end

    expect(order.status).to eq ::Order.statuses[:canceled]
    expect(order.order_histories.last.status).to eq ::Order.statuses[:canceled]
  end
end
stripe/refund.yml
---
http_interactions:
- request:
    method: get
    uri: https://api.stripe.com/v1/charges/ch_16gwnzBPgBFgcl8jurjBMKFq
    body:
      encoding: US-ASCII
      string: ''
    headers:
      X-Stripe-Client-User-Agent:
      - '{"bindings_version":"1.23.0","lang":"ruby","lang_version":"2.1.4 p265 (2014-10-27)","platform":"x86_64-linux","engine":"ruby","publisher":"stripe","uname":"Linux
        version 2.6.32-358.el6.x86_64 (mockbuild@c6b8.bsys.dev.centos.org) (gcc version
        4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) ) #1 SMP Fri Feb 22 00:31:26 UTC 2013"'
  response:
    status:
      code: 200
      message: OK
    headers:
      Stripe-Version:
      - '2015-07-07'
    body:
      encoding: UTF-8
      string: |
        {
          "id": "ch_16gwnzBPgBFgcl8jurjBMKFq",
          "object": "charge",
          "amount": 37591,
          "amount_refunded": 37591,
          "application_fee": null,
          "balance_transaction": null,
          ….

まあ、これだけでも便利なのですが、そのままだと異なるデータを返したい場合に別のカセットを
定義しないといけなくなります。

また、APIによってはオブジェクトごとにリクエストのパラメーターが変わったりタイムスタンプが
追加されたりするので、そのままだとモックにマッチしなくなります。

※これはmatch_request_on: [:path]のようなかたちでパラメーターを渡すとマッチの条件を変更することで対応できますが(Matching on Path)

VCRはyaml内にerbも書けるので下記のようにタグを埋め込んで、呼び出し時にアサイン変数を渡せば
動的にレスポンスを変更できます。

Dynamic ERB cassettes
http://www.relishapp.com/vcr/vcr/v/3-0-3/docs/cassettes/dynamic-erb-cassettes

stripe/refund.yml
---
http_interactions:
- request:
    method: get
    uri: https://api.stripe.com/v1/charges/<%= charge_id %>
  response:
    status:
      code: 200
      message: OK
    headers:
      Stripe-Version:
      - '2015-07-07'
    body:
      encoding: UTF-8
      string: |
        {
          "id": "<%= charge_id %>",
          "object": "charge",
          "amount": <%= amount %>,
          "amount_refunded": <%= amount %>,
          "application_fee": null,
          "balance_transaction": null,
          ….
describe CancelOrder do
  it 'updates status of order/history' do
    order = create(:order, :with_payment, :fixed)

    VCR.use_cassette 'stripe/refund', erb: { charge_id: order.payment.charge_id, amount: 3000 } do
      CancelOrder.new(order).execute
    end

    expect(order.status).to eq ::Order.statuses[:canceled]
    expect(order.order_histories.last.status).to eq ::Order.statuses[:canceled]
  end
end

※テストコードがあんまいい例じゃなくてすんません。

そもそもVCRを使うとあんまり外部ライブラリの実装を気にせず、スタビーなテストコードが減らせますが、
erbをつかうとさらに

  • フィクスチャ(cassette)を数を抑制できる
  • お手軽にAPIのレスポンスを変更できる

ので、いいかもしれません。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?