我有一个简单的模型:
class Category < ActiveRecord::Base
belongs_to :board
validates :name, presence: true, uniqueness: {scope: :board_id}
validates :board, presence: true
validates :display_order, presence: true, uniqueness: {scope: :board_id}
before_save :set_display_order
private
def set_display_order
last = self.board.categories.order("display_order DESC").last
self.display_order = last.display_order + 100 if last
end
end当我添加这个before_save回调时,这些测试开始失败:
it { should validate_uniqueness_of(:display_order).scoped_to(:board_id) }
it { should validate_uniqueness_of(:name).scoped_to(:board_id) }With error (如果是私有方法last = ...中的行):
NoMethodError:
undefined method `categories' for nil:NilClass其他的测试应该可以正常工作:
it { should validate_presence_of(:name) }
it { should validate_presence_of(:board) }
it { should belong_to :board }你知道这里有什么问题吗?我尝试将before_save更改为before_validation,但仍然是一样的。
发布于 2013-10-17 02:23:34
因为应该在数据库中创建记录。Gem创建记录跳过验证
http://rubydoc.info/github/thoughtbot/shoulda-matchers/master/Shoulda/Matchers/ActiveModel#validate_uniqueness_of-instance_method Ensures that the model is invalid if the given attribute is not unique. It uses the first existing record or creates a new one if no record exists in the database. It simply uses ':validate => false' to get around validations, so it will probably fail if there are 'NOT NULL' constraints. In that case, you must create a record before calling 'validate_uniqueness_of'.
在您的例子中,created category是空的,它表示category.board # => nil,您从nil调用categories方法。
您应该自己创建一条记录,用于唯一性测试。
发布于 2015-09-11 01:02:41
绕过shoulda_matchers和AR回调的这种限制的一种方法是重新定义匹配器应该使用的测试主题。
示例:
# category_spec.rb
# assuming you're using factorygirl and have this setup correctly
let(:board) { FactoryGirl.create(:board, :with_many_categories) }
subject { FactoryGirl.build(:category, board: board) }
# your shoulda matcher validations herehttps://stackoverflow.com/questions/19410519
复制相似问题