Rspec/Rails and testing validates_uniquess_of with scope
rspec, ruby-on-rails-3, shoulda, tdd
Solution
First validation failure : In your model, you have overridden the default message that rspec generates for uniqueness validation. So while testing such a validation, you have to use 'with_message' option of shoulda. So the test should be like "it { should validate_uniqueness_of(:name).scoped_to(:user_id) }.with_message('already exists')"
Second validation failure : When you write uniqueness validation spec yourself as in your second example, you have to create one record which is already present in database and build a second record with similar parameters. Then this duplicate record will not be valid and it will have errors as expected. So in before(:each) block, save the first @classroom record in database instead of just building it
Problem
Here is my test code: ``` require 'spec_helper' describe Classroom, focus: true do let(:user) { build_stubbed(:user) } describe "associations" do it { should belong_to(:user) } end describe "validations" do it { should validate_presence_of(:user) } it { should validate_uniqueness_of(:name).scoped_to(:user_id) } context "should create a unique classroom per user" do before(:each) do @class = build_stubbed(:classroom, name: "Hello World", user: user) @class2 = build_stubbed(:classroom, name: "Hello World", user: user) end it "should not create the second classroom" do @class2.should have(1).errors_on(:name) end end end describe "instance methods" do before(:each) do @classroom = build_stubbed(:classroom) end describe "archive!" do context "when a classroom is active" do it "should mark classroom as inactive" do @classroom.stub(:archive!) @classroom.active.eql? false end end end end end ``` Here is my Classroom model: ``` class Classroom < ActiveRecord::Base attr_accessible :user, :name belongs_to :user validates :user, presence: true validates_uniqueness_of :name, scope: :user_id, message: "already exists" def archive! update_attribute(:active, false) end end ``` When I run the tests, I receive the following errors: ``` 1) Classroom validations Failure/Error: it { should validate_uniqueness_of(:name).scoped_to(:user_id) } Expected errors to include "has already been taken" when name is set to "arbitrary_string", got errors: ["user can't be blank (nil)", "name already exists (\"arbitrary_string\")"] # ./spec/models/classroom_spec.rb:13:in `block (3 levels) in <top (required)>' 2) Classroom validations should create a unique classroom per user should not create the second classroom Failure/Error: @classroom2.should have(1).errors_on(:name) expected 1 errors on :name, got 0 # ./spec/models/classroom_spec.rb:24:in `block (4 levels) in <top (required)>' ``` I am fairly new to writing tests (especially with using `Rspec`). Just looking for someone to give me some advice on what I am doing wrong.