9
4

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.

Rails minitest 使い方(具体例あり) - API Controller 編

Last updated at Posted at 2019-02-08

こんにちは。@koshi_life です。

Rails minitest 使い方(具体例あり) - Mock編
に続き、実務でRailsでAPIを1本作る機会があったので、 Controller の minitest の書き方例を備忘します。

前提

  • Ruby 2.6.0
  • Rails 5.2.2
  • DB: MongoDB v4.0.4

テスト対象モジュール

ユーザがメッセージを登録できる POST /message で受け付けるシンプルなAPIをテスト対象とします。
リクエストヘッダー x-user-token が Userテーブルに登録済みの access_token に一致しない場合はエラーにするようなAPIをテスト対象モジュールとします。

準備

アプリ作成、モジュール追加、モデル作成,コントローラー作成コマンド。

$ rails new hello-rails-api --skip-active-record --api
$ cd hello-rails-api
$ echo "gem 'mongoid'" >> Gemfile
$ bundle install --path vendor/bundle
$ rails g mongoid:config
$ rails g model user email password access_token
$ rails g model message title body
$ rails g controller message

ソース

APIはのロジックは以下の通り。

app/controllers/message_controller.rb
class MessageController < ApplicationController

  # POST /messages
  def create
    title = params['title']
    body = params['body']
    email = params['email']
    token =  request.headers['x-user-token']

    # 必須パラメータが存在しない場合は 400 返却
    if title.blank? or body.blank? or email.blank? or token.blank?
      render :status=> 400, :json => {result: 'ng', code: 'ng-001'} and return
    end

    # email が存在しない場合は 404 返却
    begin
      user = User.find_by(email: email)
    rescue
      render :status=> 404, :json => {result: 'ng', code: 'ng-002'} and return
    end

    # token が一致しない場合は 403 返却
    unless user.access_token == token
      render :status=> 403, :json => {result: 'ng', code: 'ng-003'} and return
    end

    if Message.create(title: title, body: body, user_id: user.id)
      # 保存が成功したら 201 返却
      render :status=> 201, :json => {result: 'ok', code: 'ok-001'} and return
    else
      # 保存が失敗したら 500 返却
      render :status=> 500, :json => {result: 'ng', code: 'ng-004'} and return
    end
  end

end
config/routes.rb
Rails.application.routes.draw do
  post 'message', to: 'message#create'
end
app/models/user.rb
class User
  include Mongoid::Document
  field :email, type: String
  field :password, type: String
  field :access_token, type: String
  has_many :messages
end
app/models/message.rb
class Message
  include Mongoid::Document
  field :title, type: String
  field :body, type: String
  belongs_to :user
end

テストコード

DB登録失敗以外の分岐を通るようにテストケースを書いてみました。

test/controllers/message_controller_test.rb
require 'test_helper'

class MessageControllerTest < ActionDispatch::IntegrationTest

  USERS = [
    User.new(email:'taro@example.com', password: 'pass1234', access_token:'taro-token'),
  ]

  User.collection.drop
  Message.collection.drop
  USERS.each { |user| user.save }

  URL = '/message'

  test "必須パラメーター不足 400 返却" do
    # headers: x-user-token がない
    post URL, params: { title: 'title', body: 'body-1', email: 'email-1'}, as: :json
    assert_response 400
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-001', res['code'])

    # params.title がない
    post URL, headers: { 'x-user-token': 'token' }, params: { body: 'body-1', email: 'email-1'}, as: :json
    assert_response 400
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-001', res['code'])

    # params.body がない
    post URL, headers: { 'x-user-token': 'token' }, params: { title: 'title', email: 'email-1'}, as: :json
    assert_response 400
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-001', res['code'])

    # params.email がない
    post URL, headers: { 'x-user-token': 'token' }, params: { title: 'title', body: 'body-1', }, as: :json
    assert_response 400
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-001', res['code'])

    # headers, params 全部ない
    post URL
    assert_response 400
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-001', res['code'])
  end

  test "emailが存在しない 404 返却" do
    post URL, headers: { 'x-user-token': 'token' }, params: { title: 'title', body: 'body-1', email: 'ichiro@exampl.com'}, as: :json
    assert_response 404
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-002', res['code'])
  end

  test "tokenが一致しない 403 返却" do
    post URL, headers: { 'x-user-token': 'xxx' }, params: { title: 'title', body: 'body-1', email: 'taro@example.com'}, as: :json
    assert_response 403
    res = JSON.parse(response.body)
    assert_equal('ng', res['result'])
    assert_equal('ng-003', res['code'])
  end

  test "登録成功 201 返却" do
    post URL, headers: { 'x-user-token': 'taro-token' }, params: { title: 'title', body: 'body-1', email: 'taro@example.com'}, as: :json
    assert_response 201
    res = JSON.parse(response.body)
    assert_equal('ok', res['result'])
    assert_equal('ok-001', res['code'])
  end

end

実行例

$ rails test test/controllers/message_controller_test.rb 
Running via Spring preloader in process 53418
Run options: --seed 59034

# Running:

....

Finished in 0.222477s, 17.9794 runs/s, 107.8763 assertions/s.
4 runs, 24 assertions, 0 failures, 0 errors, 0 skips

簡単ですが、以上です。

9
4
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
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?