pawel7318
pawel7318

Reputation: 3573

RSpec - model uniqueness testing issue

I'm trying to make some simple model test:

/app/models/album.rb:

class Album < ActiveRecord::Base
    has_many :slides, dependent: :restrict_with_exception
    validates :name, presence: true
end

/spec/model/album_spec.rb:

require 'spec_helper'

describe Album do
    before do
        @album = Album.new(name: 'Example Album')
    end

    describe "when album name is already taken" do
        before do
            another_album = @album.dup
            another_album.save
        end

        it { should_not be_valid }
    end
end

I was expecting it to fail first (as I have no validates :uniqueness and index on the name field) but it passed. So I changed:

it { should_not be_valid } to it { should be_valid }

To see what's going on and this is what I got:

 1) Album when album name is already taken should be valid
     Failure/Error: it { should be_valid }
       expected #<Album id: nil, name: nil, created_at: nil, updated_at: nil> to be valid, but got errors: Name can't be blank
     # ./spec/models/album_spec.rb:14:in `block (3 levels) in <top (required)>'

I would like to ask you what I did wrong.

One more thing is if I can/should use expect rather than should syntax here ? I read somewhere that should is a bit deprecated and not expect is recomended but I don't know how to use it for model testing (I have it on my Controller/View test in form of expect(page) or expect(current_path). What argument can I use for model ?

Upvotes: 0

Views: 290

Answers (2)

Gardner Bickford
Gardner Bickford

Reputation: 1963

I have never seen the it syntax that you are using. First thing, I would checkout the quick start documentation available here: https://github.com/rspec/rspec-rails#model-specs and then make sure that you are familiar with this set of docs as well: http://rspec.info/

From the example on github:

require "spec_helper"

describe User do
  it "orders by last name" do
    lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
    chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")

    expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
  end
end

You would want to change your second describe to an it and then use one or more expect to determine if the test passes. it takes a string that appears in the test output. So generally you want to make it something expressive. Additionally there is no need to use before blocks here. You can do everything in the it block:

require 'spec_helper'

describe Album do
  it "fails validation when album name is already taken" do
    album = Album.new(name: 'Example Album')
    another_album = album.dup
    expect {another_album.save!}.to  raise_error(ActiveRecord::RecordInvalid,'Validation failed: This question is no longer active.')
  end
end

Upvotes: 2

Kirti Thorat
Kirti Thorat

Reputation: 53018

Setup an explicit subject before your example:

subject {@album}
it { should_not be_valid }

Currently, as per the failure error#<Album id: nil, name: nil, created_at: nil, updated_at: nil> an implicit blank instance of Album is created as no explicit subject is found before the example.

Upvotes: 1

Related Questions