RSpecでmodule内に定義したErrorを読み取ってくれない

1 min read読了の目安(約1000字

典型的な症状

Rspec uninitialized constant Error Concerns::.....

とでたら大抵これを疑った方がいい。ポイントはConcerns

原因

gemの中でConcerns::という名前空間が切られていると Railsのapp/ディレクトリ内で切ったConcerns::という名前空間と競合する、ことが、あるらしい。知らんけど

だいたいこういうやつ

module Concerns::Fee
  extend ActiveSupport::Concern
  class TooCheapError < StandardError; end
end

class Employee < ApplicationRecord
  include Concerns::Fee
end

Rspec側でこう書くとエラーになったりする

expect (subject).to raise_error(Concerns::Fee::TooCheapError)

> Rspec uninitialized constant Error Concerns::Fee::TooCheapError

対応方針

module自体は滅多にRSpecから見なくてもいいが、Errorはraise_errorのテストで使ったりする。
名前空間の競合するmoduleの中身をRspecから見ているのが原因であって、Errorをmoduleの中に書かなければいい

app/errors配下に独自エラーを定義

app/errors/... 配下なら名前空間は重複しづらい

app/errors/employee_error.rb

module EmployeeError
  class TooCheapError < StandardError; end
end

module Concerns::Fee
  extend ActiveSupport::Concern
  include EmployeeError
end

Rspec側はこう

expect (subject).to raise_error(EmployeeError::TooCheapError)

これで問題は解決できるはず