← Back to Upcase

How thorough should we test model validations in Rails?


(Hunter Stevens) #1

I am working on step 2 of the trail Testing Fundamentals:

http://exercises.upcase.com/exercises/testing-fundamentals-testing-activerecord

I submitted my first solution, which satisfied the one test case provided to us already – that a person record is invalid without a first name.

After submitting my solution, the solution I was asked to review didn’t specifically test person.valid?, but rather the error message found from an invalid record. I can’t find the solution again, but it was something like:

expect {
  Person.create!(:first_name => nil)
}.to raise_error("ActiveRecord::RecordInvalid: Validation failed: First name can't be blank")

I really liked this solution, because in a model with more than one validation, testing the error message ensures the record was invalid for the expected reason.

But is this sort of detail necessary? Would testing expect(person).to be_invalid be enough?


(Nicolas Besnard) #2

Hi :slight_smile:

I don’t think it’s the right way to test a validation:

  • Exception are slow
  • Writing the whole message is cumbersome

I usually do the following:

subject { described_class.new(first_name: nil) }

it 'is invalid' do
  expect(subject).to_not be_valid
  expect(subject).to have_error_on_field(:first_name, :blank)
end

Where have_error_on_field is a custom matcher. Which is just a check that model.errors include first_name and model.errors[:field_name] include :blank.

You can add the mode.valid? on that matcher.