Reputation: 1942
I'm starting out with Rails 4.2, and I'm try to test uniqueness for the Item models I'm making, I ran this code:
item.rb:
class Item < ActiveRecord::Base
attr_accessor :name
validates :name, uniqueness: true #, other validations...
end
item_test.rb:
require 'test_helper'
class ItemTest < ActiveSupport::TestCase
def setup
@item = Item.new(name: "Example Item")
end
test "name should be unique" do
duplicate_item = @item.dup
@item.save
assert_not duplicate_item.valid?
end
end
but the test didn't pass, saying that the assert_not
line is coming out true
when it should be nil
or false
. I basically got this code from a tutorial but cannot figure out why it's not passing. Any help?
Edit: I found the solution, by not defining the other members (specifically :price
) of @item
that I defined in the setup
action, the test passed. However now I don't know how to make it pass with the the :price
member. Below is the full implementation of item.rb & item_test.rb.
item.rb:
class Item < ActiveRecord::Base
attr_accessor :name, :description, :price
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, presence: true,
length: { maximum: 1000 }
VALID_PRICE_REGEX = /\A\d+(?:\.\d{0,2})?\z/
validates :price, presence: true,
:format => { with: VALID_PRICE_REGEX },
:numericality => {:greater_than => 0}
end
item_test.rb:
require 'test_helper'
class ItemTest < ActiveSupport::TestCase
def setup
@item = Item.new(name: "Example Item", description: "Some kind of item.", price: 1.00)
end
test "name should be unique" do
duplicate_item = @item.dup
@item.save
assert_not duplicate_item.valid?
end
end
Upvotes: 3
Views: 3979
Reputation: 1942
I fixed it, I got rid of the attr_accessor
line, the test was then able to access the attributes and was able to detect the duplication.
Upvotes: 0
Reputation: 36880
You've identified at least some of the problem in your edit.
The problem isn't that you're using Item.new
instead of Item.create
the problem is that when you do @item.save
the @item record isn't being saved because it has other validation issues.
You could try...
@item.save(validate: false)
... which will force @item
to be written to the database, but the test doesn't really determine why the duplicate_item
record is invalid.
Better might be to test that you have an error relating to name
...
require 'test_helper'
class ItemTest < ActiveSupport::TestCase
def setup
@item = Item.new(name: "Example Item")
end
test "name should be unique" do
duplicate_item = @item.dup
@item.save(validate: false)
duplicate_item.valid? # need this to populate errors
assert duplicate_item.errors
assert duplicate_item.errors[:name]
end
end
Upvotes: 3
Reputation: 13077
Almaron's answer above is correct and should be the accepted answer.
I am adding this answer to elaborate on it.
The test would be as follows:
require 'test_helper'
class ItemTest < ActiveSupport::TestCase
def setup
@item = Item.create(name: "Example Item")
end
test "name should be unique" do
duplicate_item = @item.dup
assert_not duplicate_item.valid?
end
end
Note: duplicate_item
need not be saved before validating it.
Upvotes: 5
Reputation: 4147
The uniqueness validation is performed against the records already existing in the database. And your Item.new(name: "Example Item")
is not in the database untill it is saved. So if you use Item.create(name: "Example Item")
instead, the test should pass.
Upvotes: 4