n.milsht
n.milsht

Reputation: 163

Rails, RSpec unit test failing for username

total n00b here. I'm trying to figure out how to write unit tests for my user model. It's currently failing for 4 of my tests and I'm having a hell of a time figuring out why.

The first failure is for this line...

it { should validate_uniqueness_of(:username) } fails with rails responding...

1) User should require case sensitive unique value for username
     Failure/Error: it { should validate_uniqueness_of(:username) }

     ActiveRecord::StatementInvalid:
       PG::NotNullViolation: ERROR:  null value in column "seeking_coach" violates not-null constraint
       DETAIL:  Failing row contains (1, , , , , a, , , , , null, null, null, null, null, null, 0, null, null, null, null, 2016-10-30 19:17:07.366431, 2016-10-30 19:17:07.366431, f, null, null, null).
       : INSERT INTO "users" ("username", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"

Why is this unit test of username failing due to a null field while the prior unit test (it { should have_valid(:username).when('Groucho', 'Marx')}) passes?

spec/models/user_spec.rb

  it { should have_valid(:username).when('Groucho', 'Marx')}
  it { should_not have_valid(:username).when(nil, '')}
  it { should validate_uniqueness_of(:username) }

models/user.rb

  validates :username, uniqueness: true, presence: true
  validates_format_of :username, with: /\A[a-zA-Z0-9]+\z/

Upvotes: 0

Views: 337

Answers (1)

David
David

Reputation: 3610

Ok, having read around it appears this may actually be a bug related to the shoulda matcher for some edge case when testing for uniqueness with a NOT NULL database constraint on a different column.

https://github.com/thoughtbot/shoulda-matchers/issues/600

As a workaround I would suggest that you explicitly set up a valid model and allow the shoulda matcher to do its own thing on the attribute to be tested. You can set the subject that all shoulda matchers should use like so:

describe User do
  subject { User.new(
    username: 'username',
    seeking_coach: 'coach',
    #
    # set other valid attributes here
    #
  )}

  it { should have_valid(:username).when('Groucho', 'Marx')}
  it { should_not have_valid(:username).when(nil, '')}
  it { should validate_uniqueness_of(:username) }
end

Of course if you are using FactoryGirl, and have a user factory that can build a valid user, then you can simply use:

subject { FactoryGirl.build(:user) }

Now all the shoulda matcher tests will use that object to run the tests with, and you shouldn't get database constraint issues for an attribute you aren't testing.

Upvotes: 2

Related Questions