无法通过shoulda matcher进行唯一性验证测试

26
我是一名有用的助手,可以为您翻译文本。
我在avatar_parts_spec.rb中使用了一个shoulda匹配器,但无法通过测试:
测试:
require 'rails_helper'

RSpec.describe AvatarPart, :type => :model do
  it { should validate_presence_of(:name) }
  it { should validate_presence_of(:type) }
  it { should validate_uniqueness_of(:name).case_insensitive }
  it { should belong_to(:avatar) }
end

模型:

class AvatarPart < ActiveRecord::Base
  attr_accessible :name, :type, :avatar_id

  belongs_to :avatar

  validates_uniqueness_of :name, case_sensitive: false
  validates :name, :type, presence: true, allow_blank: false
end

移植:
class CreateAvatarParts < ActiveRecord::Migration
  def change
    create_table :avatar_parts do |t|
      t.string :name, null: false
      t.string :type, null: false
      t.integer :avatar_id      

      t.timestamps
    end
  end
end

错误:

 1) AvatarPart should require unique value for name
     Failure/Error: it { should validate_uniqueness_of(:name).case_insensitive }
     ActiveRecord::StatementInvalid:
       SQLite3::ConstraintException: NOT NULL constraint failed: avatar_parts.type: INSERT INTO "avatar_parts" ("avatar_id", "created_at", "name", "type", "updated_at") VALUES (?, ?, ?, ?, ?)

什么可能是错误的原因?
编辑: Github仓库:https://github.com/preciz/avatar_parts
2个回答

58

该匹配器的文档指出:

这个匹配器的工作方式与其他匹配器略有不同。正如之前所指出的,如果模型实例不存在,它将创建一个。有时这一步会失败,特别是如果您对除唯一属性之外的任何属性设置了数据库级别的限制。在这种情况下,解决方法是在调用 validate_uniqueness_of 之前填充这些属性。

因此,在您的情况下,解决方案可能是:

  describe "uniqueness" do
    subject { AvatarPart.new(name: "something", type: "something else") }
    it { should validate_uniqueness_of(:name).case_insensitive }
  end

有时似乎需要,有时又不需要。很奇怪。 - Joshua Muheim
为什么这里需要 case_insensitive - Vishal Vijay
3
@VishalVijay 在原始问题中提到了这一点,但它并不是答案特别实质性的部分。 - Dave Slutzkin

5
除了上述内容,我使用的另一种解决方法是:

此外,我使用的一种模式可以解决这个问题:

RSpec.describe AvatarPart, :type => :model
  describe 'validations' do
    let!(:avatar_part) { create(:avatar_part) }

    it { should validate_uniqueness_of(:some_attribute) }
    it { should validate_uniqueness_of(:other_attribute) }
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接