LoginSignup
2
4

More than 3 years have passed since last update.

Ruby Privateなインスタンスメソッド/クラスメソッドのテストを書く

Last updated at Posted at 2019-05-15

@koshi_life です。

最近、Ruby関連のプロジェクトでテスト書いたり、リファクタしたりしています。そこでPrivate宣言したメソッドのテストの書き方を調べたので備忘です。

結論 Object#send を使う

Object#send メソッドを用いることで、Private宣言したメソッドをクラス外から呼び出しが可能です。

ちなみに、privateメソッドがコールできてしまうRubyの言語仕様/背景について以下エントリが参考になりました。

Ruby の private と protected 。歴史と使い分け

前提

  • Rails 5.2.3
  • Ruby 2.6.0
  • minitest 5.11.3

対象クラス

hoge.rb
class Hoge
  # クラスメソッド
  def self.pr_class_method(arg1, arg2)
    "pr_class_method arg1=#{arg1} arg2=#{arg2}"
  end

  # クラスメソッド (キーワード引数)
  def self.pr_class_method_kw(arg1:, arg2:)
    "pr_class_method_kw arg1=#{arg1} arg2=#{arg2}"
  end

  # クラスメソッド (Block利用)
  def self.pr_class_method_blk(arg1, &blk)
    blk.call(arg1) if block_given?
    "pr_class_method_blk arg1=#{arg1}"
  end

  private_class_method :pr_class_method,
                       :pr_class_method_kw,
                       :pr_class_method_blk

  private

  # インスタンスメソッド
  def pr_instance_method(arg1, arg2)
    "pr_instance_method arg1=#{arg1} arg2=#{arg2}"
  end

end

send検証

$ rails c

# <インスタンスメソッド> 普通に呼ぶと NoMethodError エラー
> hoge = Hoge.new
> hoge.pr_instance_method(1,2)
# NoMethodError (private method `pr_instance_method' called for #<Hoge:0x00007ff7501ab338>)

# <インスタンスメソッド> sendで呼ぶ
> hoge.send(:pr_instance_method, 1, 2)
=> "pr_instance_method arg1=1 arg2=2"

# <クラスメソッド> 普通に呼ぶと NoMethodError エラー
> Hoge.pr_class_method(1, 2)
# NoMethodError (private method `pr_class_method' called for Hoge:Class)

# <クラスメソッド> sendで呼ぶ
> Hoge.send(:pr_class_method, 1, 2)
=> "pr_class_method arg1=1 arg2=2"

# <クラスメソッド> sendで呼ぶ  (keyword引数)(blk引数)
> Hoge.send(:pr_class_method_kw, {arg1:'kw1', arg2:'kw2'})
=> "pr_class_method_kw arg1=kw1 arg2=kw2"

# <クラスメソッド> sendで呼ぶ (blk引数)
> Hoge.send(:pr_class_method_blk, 'blk-arg1') {|arg1| puts "it is block. arg1=#{arg1}"}
it is block. arg1=blk-arg1
=> "pr_class_method_blk arg1=blk-arg1"

テストコード

hoge_test.rb
require 'test_helper'

class HogeTest < ActiveSupport::TestCase
  test 'Private Methodのテスト' do
    # インスタンスメソッド
    hoge = Hoge.new
    actual1 = hoge.send(:pr_instance_method, 'i-A1', 'i-A2')
    assert_equal('pr_instance_method arg1=i-A1 arg2=i-A2', actual1)

    # クラスメソッド
    actual2 = Hoge.send(:pr_class_method, 'c-A1', 'c-A2')
    assert_equal('pr_class_method arg1=c-A1 arg2=c-A2', actual2)

    # クラスメソッド (キーワード引数)
    actual3 = Hoge.send(:pr_class_method_kw, { arg1: 'ckw-A1', arg2: 'ckw-A2' })
    assert_equal('pr_class_method_kw arg1=ckw-A1 arg2=ckw-A2', actual3)
  end
end

参考

2
4
2

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