如何正确使用具有唯一性验证的 shoulda 匹配器?

Dan*_*bio 4 rspec ruby-on-rails

我正在尝试将 rspec 和 shoulda 匹配器作为我的新测试框架,但我对如何通过should validate_uniqueness_of(:attribute)测试感到有些困惑。这是我的简单模型:

class Employee < ActiveRecord::Base
  validates :name, presence: true
  validates :title, presence: true
  validates :department, presence: true
  validates :avatar, presence: true 
  validates :email, presence: true, uniqueness: true
  validates :reports_to, presence: true
  mount_uploader :avatar, EmployeeAvatarUploader, on: :file_name
end
Run Code Online (Sandbox Code Playgroud)

这是初始测试:

RSpec.describe Employee, type: :model do
  it { should validate_presence_of(:name) }
  it { should validate_presence_of(:title) }
  it { should validate_presence_of(:department) }
  it { should validate_presence_of(:avatar) }
  it { should validate_presence_of(:email) }
  it { should validate_uniqueness_of(:email) } 
  it { should validate_presence_of(:reports_to) }
end
Run Code Online (Sandbox Code Playgroud)

这失败了,并在下面粘贴了错误的描述:

`1) Employee should validate uniqueness of email
 Failure/Error: should validate_uniqueness_of(:email)

 Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher::ExistingRecordInvalid:
   validate_uniqueness_of works by matching a new record against an
   existing record. If there is no existing record, it will create one
   using the record you provide.

   While doing this, the following error was raised:

     PG::NotNullViolation: ERROR:  null value in column "title" violates not-null constraint
     DETAIL:  Failing row contains (21, null, null, null, null, null, null, 2017-06-27 01:07:49.125445, 2017-06-27 01:07:49.125445, null, null).
     : INSERT INTO "employees" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"

   The best way to fix this is to provide the matcher with a record where
   any required attributes are filled in with valid values beforehand.`
Run Code Online (Sandbox Code Playgroud)

所以我对文档的印象是我的测试应该按原样工作。从 shoulda 匹配器文档中,我尝试了这个版本的测试:

RSpec.describe Employee, type: :model do
  it { should validate_presence_of(:name) }
  it { should validate_presence_of(:title) }
  it { should validate_presence_of(:department) }
  it { should validate_presence_of(:avatar) }
  it { should validate_presence_of(:email) }
  it 'should validate uniqueness of email' do
    email1 = FactoryGirl.create(:account, email: 'email@blackducksoftware.com')
    email2 = FactoryGirl.build(:account, email: 'email@blackducksoftware.com' )
    should validate_uniqueness_of(:email)
  end
  it { should validate_presence_of(:reports_to) }
end
Run Code Online (Sandbox Code Playgroud)

这似乎也不起作用。然后我尝试了通过单击此链接的Rspec validates_uniqueness_of找到的此测试的变体

但仍然没有运气。有人可以指导我使用正确的方法进行验证吗?

tre*_*iff 9

你应该可以这样称呼它:

describe "validations" do
  subject { Employee.new(title: "Here is the content") }
  it { should validate_uniqueness_of(:email) }
end
Run Code Online (Sandbox Code Playgroud)

或与FactoryGirl

describe "validations" do
  subject { FactoryGirl.build(:employee) }
  it { should validate_uniqueness_of(:email) }
end
Run Code Online (Sandbox Code Playgroud)

您的employees表有一个需要 的数据库级约束title,因此您需要先创建一个有效的employee对象。

在您的第二个示例中,您似乎正在构建一个account而不是employee.

在此处查看文档:文档