LoginSignup
0
1

More than 3 years have passed since last update.

Rails minitest Mockで例外発生パターンのテスト

Posted at

@koshi_life です。

Rails 標準のテストフレームワーク minitest にて Mock側で例外を発生させるテストケースの書き方の備忘です。

前提

  • Rails 5.2.3
  • Ruby 2.6.0
  • minitest 5.11.3

検証対象モジュール

api_clientをコンストラクタ引数で取り、テスト対象のcoutup関数は、引数のitem_idをAPI経由(#get)で取得し、値に1加えてAPI経由(#update)で更新する簡素な内容です。

fuga.rb
class Fuga
  def initialize(api_client)
    @api_client = api_client
  end

  def countup(item_id)
    error_code = 0

    # APIでItem取得
    begin
      item = @api_client.get(item_id)
    rescue StandardError => e
      # Case1: テストではココの分岐に入ることを確認します
      error_code = 1
      return false, error_code
    end

    # APIでItemの値更新
    begin
      @api_client.update(item_id, item[:val] + 1)
    rescue StandardError => e
      # Case2: テストではココの分岐に入ることを確認します
      error_code = 2
      return false, error_code
    end
    return true, error_code
  end
end

テストコード

api_clientをMock化します。api_client#get, api_client#updateコール時に例外を捕捉する分岐を通るケースを書いてみます。

Mock#expect-instance_method より

#expect(name, retval, args = [], &blk) ⇒ Object

&blkの Procを利用して例外を発生させることができます。

fuga_test.rb
require 'test_helper'

class FugaTest < ActiveSupport::TestCase
  test 'Case1: api_client#getで例外発生' do
    item_id = 'id-1'
    retval_get = { val: 1 }
    args_get = [item_id]

    api_mock = MiniTest::Mock.new
    api_mock.expect(:get, retval_get) do |args_update|
      raise StandardError('Mock#getで例外発生')
    end

    # 検証したいモジュールを実行します
    fuga = Fuga.new(api_mock)
    result, error_code = fuga.countup(item_id)
    assert_equal(false, result)
    assert_equal(1, error_code)

    # Mockに送信されたデータを検証します。
    api_mock.verify
  end

  test 'Case2: api_client#updateで例外発生' do
    item_id = 'id-2'
    retval_get = { val: 2 }
    args_get = [item_id]

    retval_update = nil
    args_update = [item_id, 3]

    api_mock = MiniTest::Mock.new
    api_mock.expect(:get, retval_get, args_get)
    api_mock.expect(:update, retval_update) do |args_update|
      raise StandardError('Fuga#updateで例外発生')
    end

    # 検証したいモジュールを実行します
    fuga = Fuga.new(api_mock)
    result, error_code = fuga.countup(item_id)
    assert_equal(false, result)
    assert_equal(2, error_code)

    # Mockに送信されたデータを検証します。
    api_mock.verify
  end

  test '参考: 比較用に正常系' do
    item_id = 'id-3'
    retval_get = { val: 3 }
    args_get = [item_id]

    retval_update = true
    args_update = [item_id, 4]

    api_mock = MiniTest::Mock.new
    api_mock.expect(:get, retval_get, args_get)
    api_mock.expect(:update, retval_update, args_update)

    # 検証したいモジュールを実行します
    fuga = Fuga.new(api_mock)
    result, _ = fuga.countup(item_id)
    assert_equal(true, result)

    # Mockに送信されたデータを検証します。
    api_mock.verify
  end
end

参考

0
1
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
0
1