オルトプラスエンジニアの日常をお伝えします!

Ruby on RailsでWebMockを利用する

※ この記事は「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などを利用してきましたが、ここで得た考え方を他言語でも上手く応用できればと考えています。