0

我有 2 个模型:Answer 和 Book。

尽管它们非常相似,但所有测试都通过了 Answer,但 Book 的 1 次测试失败

模型/answer.rb

class Answer < ApplicationRecord
  belongs_to :question, class_name: "Question", foreign_key: "question_id"

  validates :text, presence: true
  validates :correct, presence: true
  validates :question_id, presence: true
end

模型/book.rb

class Book < ApplicationRecord
  belongs_to :grade, class_name: "Grade", foreign_key: "grade_id"

  validates :name, presence: true, uniqueness: { case_sensitive: false }
  validates :grade_id, presence: true  
end

规格/工厂/answers.rb

FactoryBot.define do
  factory :answer do
    text { Faker::Book.author }
    correct { %i(false, true).sample }
    question
  end
end

规格/工厂/books.rb

FactoryBot.define do
  factory :book do
    name { Faker::Book.title }
    grade
  end
end

spect/models/answer_spec.rb

require 'rails_helper'

RSpec.describe Answer, type: :model do

  describe 'validation' do
    it { should validate_presence_of(:text) }
    it { should validate_presence_of(:correct) }
    it { should validate_presence_of(:question_id) }
    it { should belong_to :question }
  end
end

spect/models/book_spec.rb

require 'rails_helper'

RSpec.describe Book, type: :model do

  describe 'validation' do
    it { should validate_presence_of(:name) }
    it { should validate_uniqueness_of(:name).case_insensitive }
    it { should validate_presence_of(:grade_id) }
    it { should belong_to :grade }
  end
end

我得到的回报是:

  1. 书籍验证应验证 :name 是不区分大小写的唯一失败/错误:它 { should validate_uniqueness_of(:name).case_insensitive }

    Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher::ExistingRecordInvalid: validate_uniqueness_of 通过将新记录与现有记录进行匹配来工作。如果没有现有记录,它将使用您提供的记录创建一个。

    While doing this, the following error was raised:
    
      **PG::NotNullViolation: ERROR:  null value in column "grade_id" violates not-null constraint**
      DETAIL:  Failing row contains (2, null, null, 2021-12-23 15:03:39.977355, 2021-12-23 15:03:39.977355).
    
    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.
    

我已经尝试了许多我想出或在堆栈/git 帖子中看到的方法,但没有一个接缝可以工作。

4

2 回答 2

2

这种情况包含在validates_uniqueness_of 文档中。

如果没有现有记录,它将使用您提供的记录创建一个。

你的规范没有说明如何创建一本书,它也不知道它需要一个等级。你需要告诉它,它不会使用工厂。通过添加一个主题供您的单行使用来做到这一点。

require 'rails_helper'

RSpec.describe Book, type: :model do
  subject { build(:book) }

  describe 'validation' do
    it { should validate_presence_of(:name) }
    it { should validate_uniqueness_of(:name).case_insensitive }
    it { should belong_to :grade }
  end
end

请注意,it { should validate_presence_of(:grade_id) }it { should belong_to :grade }. belongs_to 已经验证了存在。

于 2021-12-23T17:23:38.027 回答
2

当尝试在具有参考的模型中测试唯一性时,您需要先提供一个进行比较。

为此,您应该指定主题:

 describe 'validation' do
    subject{ 
    }

之后,您可以调用 FactoryBot 来构建要完成的任务:

FactoryBot.build(:book)

最终片段:

  describe 'validation' do
    subject{ 
     FactoryBot.build(:book)
    }

[Schwern][1] 先生对代码进行了更好的改进:

describe 'validation' do
  subject{ build(:book)}
于 2021-12-23T16:51:36.377 回答