実はこれまで webmock を使う必要がなかったので試しに API client を書く際に webmock でテストを書いてみた。そんで先日書いてみた Pact の mock service と比べてみた。
それぞれ GitHub 上の README より抜粋したコードを貼りつつメモ。
webmock
GitHub - bblimke/webmock: Library for stubbing and setting expectations on HTTP requests in Ruby.
stub_request(:post, "www.example.com").
with(body: "abc", headers: { 'Content-Length' => 3 })
webmock は元のクライアントに一切手を加える必要がないのが特徴。
- その代わりに request 先を正確に指定しないといけない
- サンプルには書かれていなかったけど User Agent も正しく Header で指定しないとダメっぽい
Pact service consumer
animal_service.given("an alligator exists").
upon_receiving("a request for an alligator").
with(method: :get, path: '/alligator', query: '').
will_respond_with(
status: 200,
headers: {'Content-Type' => 'application/json'},
body: {name: 'Betty'} )
Pact の mock service は localhost で受け付けるのが前提。
- consumer の機能で endpoint を切り替える
- クライアント側のテストだけを考えると service_name も provider state ( given ) も description ( upon receiving ) も RSpec なり Minitest なりのメタデータ以外に指定しないといけないのが面倒
- request / response はいい具合に抽象化しやすい
- response を {} と書くとその内容まではチェックしない
- Pact.each_like({}) とすれば {} の個数もチェックしない
webmock の方がまだまだポピュラーではあると思うが、サービス同士のテストにはやはり Pact の方が書きやすいように思う。Pact は最初の設定(名前決めなど)以外の実際の mocking の部分は結構書きやすいし、response body を厳密に決める必要がないので、provider 側を書く前のテストとしてはとても書きやすいと思った。
API を実装していく際にリンク先の URI も加えてあげたい1場合、どこかで URI を生成する必要がある。
Grape で API を書く場合、提供される機能はあくまで endpoint 周りであって、アプリの内部実装は自分でなんとかする必要がある。Grape から使えるとしたら Rails の C でも V でもない場所にせざるを得ない。ということで C でも V でもない場所で URI を扱う方法を調べてみた。
Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models? - Stack Overflow
ということで
Rails.application.routes.url_helpers
を include すれば使えそうだが、その際 include する人は module でなく class でないとダメ っぽい。
これは C や V で利用することを前提に url_for() ができあがっているからか、もしくは自分が独自に作った Helper が super な url_for() を呼び出している際に何かの依存を踏んでいるからかもしれない。ちょっとよく分かっていないけど少なくとも class で include されるようにしておけば安定して動くことが分かった。
[20160731 追記] こんな記事があった。ほぼ考えてることそのまんまだった。
- <a
- href=”http://postd.cc/sprinkle-some-hateoas-on-your-rails-apis/”>RailsのAPIにHATEOASを散りばめてみる
RESTの拡張、HATEOASの詳解と実装例 プログラミング POSTD</a>
HATEOASですね ↩