Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save kamillle/7cc9c64ce43cc0dfbf5e95efd46686ca to your computer and use it in GitHub Desktop.
Save kamillle/7cc9c64ce43cc0dfbf5e95efd46686ca to your computer and use it in GitHub Desktop.

ActiveModel::Attributes APIの attribute メソッドを使用して値のcastを行う場合に、shoulda-matchersが提供するマッチャを使ってバリデーションのテストを行おうとすると 意図しない挙動によってテストが落ちてしまう。

サンプルコード

class SampleForm
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :user_id, :integer

  validates :user_id, numericality: { greater_than_or_equal_to: 1 }, allow_nil: true
end

RSpec.describe SampleForm, type: :model do
    it { is_expected.to validate_presence_of(:user_id).allow_nil }
end

エラー内容

presenceを検証するテストなので、 "" を渡したら落ちる(invalid判定される)けど、 ""nil にcastされていて落ちないからおかしいよ。って言ってる。

  1) SampleForm should validate that :user_id cannot be empty/falsy
     Failure/Error: it { is_expected.to validate_presence_of(:user_id) }

       Expected SampleForm to validate that :user_id cannot
       be empty/falsy, but this could not be proved.
         After setting :user_id to ‹""› -- which was read back as ‹nil› -- the
         matcher expected the SampleForm to be invalid, but
         it was valid instead.

         As indicated in the message above, :user_id seems to be changing
         certain values as they are set, and this could have something to do
         with why this test is failing. If you've overridden the writer method
         for this attribute, then you may need to change it to make this test
         pass, or do something else entirely.
     # ./spec/forms/sample_form_spec.rb:9:in `block (2 levels) in <top (required)>'

Finished in 1.26 seconds (files took 3.19 seconds to load)
1 example, 1 failure
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment