Search code examples
rubyruby-on-rails-4factory-botrspec-rails

Rspec and FactoryGirl Uniqueness Failing


I'll be brief with the code samples, as all of my tests pass except the one below. I got it to pass by changing things up a bit, but I'm not sure why version 1 fails and version 2 works.

My model:

# app/models/person.rb
class Person
validates :contact_number, uniqueness: true
end

Model spec

# spec/models/person_spec.rb
require 'spec_helper'
describe Person do
  it 'is a valid factory' do
    create(:person).should be_valid # passes
  end

  it 'has a unique phone number' do
    create(:person)
    build(:person).should_not be_valid # fails
  end

  it 'also has a unique phone number' do
    person1 = create(:person)
    person2 = person1.dup
    person2.should_not be_valid # passes
  end
end

As far as I can tell, the two uniqueness tests should be doing the same thing, however one passes and one fails.

If it matters, I am using mongoid, though I don't think that should have any effect. I'm also not doing anything with nested contexts or describes in my test, so I think the scope is correct. Any insight is appreciated.

UPDATE 1: I realized in my factory I am adding an initialize_with block like this:

initialize_with { Person.find_or_create_by(contact_number: contact_number) }

I realized that this may be the reason the validation was failing -- I was just getting the same person back. However, commenting out that line gives the following error:

Mongoid::Errors::Validations: Problem: Validation of Person failed. Summary: The following errors were found: Contact number is already taken Resolution: Try persisting the document with valid data or remove the validations.

Which, in theory is good, I suppose, since it won't let me save a second person with the same contact number, but I'd prefer my test to pass.


Solution

  • I figured it out! On a whim, I checked out the test database and noticed that a Person object was lingering around. So, it actually wasn't the build(:person).should_not be_valid that was raising the Mongoid exception. It was the create call on the line before. Clearing out the DB and running the spec again passed, but again the data was persisting. I double checked my spec_helper.rb file and noticed I wasn't calling start on the DatabaseCleaner. My updated spec_helper.rb file looks like this, and now everything works:

    # Clean up the database
    require 'database_cleaner'
    
    config.mock_with :rspec
    
    config.before(:suite) do
      DatabaseCleaner.strategy = :truncation
      DatabaseCleaner.orm = "mongoid"
    end
    
    config.before(:each) do
      DatabaseCleaner.start
    end
    
    config.after(:each) do
      DatabaseCleaner.clean
    end