Railsのmodelでprivateメソッドのロジックをテストしない
みなさんはRailsのモデルでprivateメソッドをテストしますか?
僕はしません。
理由はpublicメソッドではないからです。
Privateメソッドをテストするって理由の一つが、「privateメソッドのロジックをテストしたい」だと思います。
ふーん、でもそのロジックはそのモデルにあるべきなんでしょうか?そして、そのモデルでテストするべきなのでしょうか?
他のモデルで同じロジックを使いたいときはどうするのでしょうか?
Railsにはconcernという機能がありますが、僕は基本使わなくなりました。
なせ?単純にいらないからですw
嘘です、必要です。そもそもconcernの存在意義が、ロジックを共通化するものではないというだけです。
では、どうするのか?
そのロジック用のモデルを作成することで解決できます。
具体的にやってみましょう。
Humanモデルにロジックを書いてみる
class Creature include ActiveModel::Model include AcitveMode::Attributes attribute :name, :string end class Human < Creature private def hello "Hello #{name}!" end def hi "Hi #{name}!" end end
hello
と hi
メソッドをテストしたいよね?
でも、privateメソッド、、
ならば!
Greetモデルを作成してみる
class Human < Creature private def greet @greet ||= Greet.new(creature: self) end end
class Greet include ActiveModel::Model include AcitveMode::Attributes attribute :creature def hello "Hello #{creature&.name}!" end def hi "Hi #{creature&.name}!" end end
どうでしょうか?
これでprivateメソッドのテストは不要になりますね。(Greetモデルのテストで担保するため)
さらに移譲してみましょう。
class Human < Creature delegate :hello, :hi, to: :greet private def greet @greet ||= Greet.new(creature: self) end end
irb>human = Human.new(name: 'murajun1978') irb>human.hello #=> "Hello murajun1978!" irb>human.hi #=> "Hi murajun1978!"
みなさんも、新しいロジックがひょこっと出てきたら、新しいモデルを作成しましょう。
そのモデルをテストすることで品質も担保できますしね。