※ この記事は「AltPlus Advent Calendar 2016」の15日目の記事です。
id:aptake です。
サーバサイドのエンジニアを担当しています。
現在、Ruby on Railsで、スマートフォン向けアプリのサーバサイド開発を進めています。
今回は開発の過程で利用した、WebMockというGemについて書きたいと思います。
WebMockとは
HTTPリクエストする場合などに、リクエスト部分をスタブ化できるライブラリです。
環境
- Ruby 2.3.1
- Rails 5.0.0.1
インストール
Gemfileに記述して、Bundlerでインストールします。
本番環境では利用しない想定なので、development環境限定でインストールするようにしています。
group :development do gem "webmock" end
準備
HTTPリクエストするソースコードです。
class Api def request_api uri = URI.parse("http://example.com/api") http = Net::HTTP.new(uri.host, uri.port) http.start do |_h| req = Net::HTTP::Get.new(uri, { "Content-Type" => "application/json" }) http.request(req) end end end
実装
Apiクラスに対して、WebMockの実装を加えていきます。
1. スタブモジュールApiStubを実装
ここでは、test/stub/api_stub.rbに実装していきます。
module ApiStub WebMock.enable! def request_api WebMock.stub_request(:get, "http://example.com/api").to_return( body: File.read("#{Rails.root}/test/json/api_get.json"), status: 200, headers: { "Content-Type" => "application/json" } ) super end end
やっていること
- WebMock.enable!で、WebMockを有効にする
- リクエストスタブ登録するメソッドをオーバーライドさせるので、Apiクラスの当該メソッドと同名で実装
- stub_requestメソッドで、スタブ化するURIを設定
- to_returnメソッドで、期待するレスポンスを設定
- bodyはファイルに外出し
2. ApiクラスにスタブモジュールApiStubをprepend
class Api prepend ApiStub if Rails.env.development? # 追加 def request_api uri = URI.parse("https://example.com/api")
やっていること
- development環境でのみprependさせるための後置if
3. スタブモジュールをrequire
config/enviroments/development.rbに以下の実装を追加します。
WebMock.allow_net_connect!(net_http_connect_on_start: true) Dir[Rails.root.join("test/stub/*.rb")].each do |file| require file end
やっていること
- WebMock.allow_net_connect!で、リクエストスタブ登録していないHTTPリクエストは通常動作するよう設定
- Dir[Rails.root.join("test/stub/*.rb")].each ~ で、test/stub配下にあるファイル(スタブモジュール)をrequire
実行
api = Api.new
api.request_api
ApiクラスにはApiStubモジュールがprependされているため、これでスタブが実行されます。
最後に
今回、内製のWebAPIを利用すること、そのWebAPIにアクセス制限をかけていることもあり、アクセス制限を気にせず作業するためにWebMockを導入しました。
実はRuby on Railsを始めて3,4ヶ月で、まだまだ初心者です。
最初はRubyの書き方に戸惑ったものですが、最近ちょっと慣れてきたような気がしています。
覚えるのは大変ですが、自分に無かった考え方も入ってくるので新鮮です。
今まで、PHP, C, Javaなどを利用してきましたが、ここで得た考え方を他言語でも上手く応用できればと考えています。