RspecでAPIのテストする方法です。今回はPOSTリクエストです。
目次
完成コード
まずは完成コードから掲載したいと思います。
spec/requests/api/vi/user_spec.rb
require 'rails_helper' RSpec.describe 'ユーザー新規作成API', type: :request do describe 'POST /api/v1/users/create.json' do let(:request_header) do { 'CONTENT_TYPE' => 'application/json', 'ACCEPT' => 'application/json' } end let(:user) do '{"name": "testuser", "profile": "testuser", "email": "user1@test.com", "password": "testtesttest", "password_confirmation": "testtesttest"}' end subject do post api_v1_users_create_path(format: :json), user, request_header end context "正常系" do it "ユーザーが作成される" do expect { subject }.to change(User, :count).by(1) end it "200を返す" do subject expect(response).to be_success end it "JSONに含まれるキーが適切である" do subject result = JSON.parse(response.body) expect(result).to have_key('result') expect(result).to have_key('message') expect(result).to have_key('error_code') end end context "異常系" do context "すでにユーザーが存在する" do before do create(:user, email: "user1@test.com") end it "エラーが返ってくる" do subject body = JSON.parse(response.body) expect(body["result"]).to eq false expect(body["message"]).to eq ["メールアドレスはすでに存在します"] expect(body["error_code"]).to eq 3 end end context "メール、パスワードが未記入" do let(:valid_user) do '{"name": "testuser", "profile": "testuser", "email": "", "password": "", "password_confirmation": "testtesttest"}' end before do post api_v1_users_create_path(format: :json), valid_user, request_header end it "エラーが返ってくる" do body = JSON.parse(response.body) expect(body["result"]).to eq false expect(body["message"]).to include "メールアドレスを入力してください" expect(body["message"]).to include "パスワードを入力してください" expect(body["error_code"]).to eq 3 end end end end end
解説
requestsで作成する
controller specではなく、request specで作成する方法が一般的のようです。
request_headerを定義する
request_headerをletで定義してpostする際に使う必要があります。
request spec – Request specs – RSpec Rails – RSpec – Relish
FactoryGirlを使わない
はじめはFactoryGirlのattributes_forメソッドでJSONテストデータを作成していましたが、うまくいきませんでした。そのためべた打ちしてます。
RailsはデフォルトでJSONをwrapしてくれる
今回の場合,
let(:user) { {user: FactoryGirl.attributes_for(:user) }}
のようにuserでwrapしてあげるとFactoryGirlを使ってもうまくいきます。
しかし、今回はwrapせずともPOSTリクエストを受け付けることを検証したかったため、べた打ちでテストデータを書きました。
テストデータはuserでwrapされていませんが、実際は
{"user": {"name": "hoge", "profile": "test", "email": "hoge@gehoff.com", "password": "testtesttest", "password_confirmation": "testtesttest", "sex": "male", "birth_date": "2000-01-01 00:00:00", "agreement": "1", "telephone_number": "000-1111-2222", "address1": "住所1", "address2": "住所2", "status": "active", "pay_type": "CreditCard"}}
のようにuserでwarpしてくれます。
そのコードはconfig/initializers/wrap_parameters.rb
に定義されています。
# Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] if respond_to?(:wrap_parameters) end # To enable root element in JSON for ActiveRecord objects. # ActiveSupport.on_load(:active_record) do # self.include_root_in_json = true # end
これでcontroller名に沿ってparameterをwrapしてくれます。
controller名に沿っていない場合はcontrollerで定義する必要があります。
今回私の場合もdeviseを使っていてcontroller名に沿っていないため、別途定義しました。
app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController wrap_parameters :user, format: [:json]
keyのテスト
expect(result).to have_key('result')
でPOSTリクエストに対するレスポンスパラメータのkeyをテストすることができます。
今回はjbuilderで定義しました。
errorコードのテスト
エラーコードもcontrollerとjbuilderで定義するとテストできます。
special thanks
RSpecでJSONによるPOSTリクエストをテスト | EasyRamble

- 作者: すがわらまさのり,前島真一,近藤宇智朗,橋立友宏
- 出版社/メーカー: 技術評論社
- 発売日: 2014/10/31
- メディア: Kindle版
- この商品を含むブログ (1件) を見る
コメントを残す