RSpec / Rails / Ruby

連載: Rails4のActiveRecord向けRSpecカスタムマッチャ5選

外部キー制約のあるモデルに対してshoulda-matchersvalidate_uniqueness_ofカスタムマッチャを使うと

Failure/Error: it { should validate_uniqueness_of(:code) }
ActiveRecord::InvalidForeignKey:
 Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails

というエラーが出てしまい、ちゃんとテストできないのでsafely_validate_uniqueness_ofというカスタムマッチャを作りました。

このカスタムマッチャを使うと

describe Person do
  it { should safely_validate_uniqueness_of(:code) }
  it { should safely_validate_uniqueness_of(:group_id, :number) }
end

と書くことで

$ bundle exec rspec spec/models/person_spec.rb
Person
  should require unique value for code
  should require unique value for group_id, number

とテストできるようになります。

カスタムマッチャは

RSpec::Matchers.define :safely_validate_uniqueness_of do |*fields|
  match do |model|
    name = model.class.table_name.singularize
    record = create(name)
    other_record = build(name)

    fields.each do |field|
      other_record.send("#{field}=", record.send(field))
    end

    begin
      other_record.save!
      false
    rescue ActiveRecord::RecordInvalid
      true
    end
  end

  description { "require unique value for #{fields.join(", ")}" }
  failure_message { "expected to require unique value for #{fields.join(", ")}, but not" }
end

となります。

ほんとはshoulda-matchersにPR投げた方が良いんですけどね。

関連記事