代码之家  ›  专栏  ›  技术社区  ›  Ronan Lopes

FactoryBot-创建嵌套对象

  •  2
  • Ronan Lopes  · 技术社区  · 6 年前

    我正在学习如何在Rails中进行测试,我正在为我的问题模型编写一个工厂:

    require 'factory_bot'
    
    FactoryBot.define do
      factory :question do
        sequence(:content) { |n| "question#{n}" }
        source "BBC"
        year "1999"
      end
    end 
    

    问题是我有一个 has_many :choices 关系,我的问题应该有5个选择。所以我想知道如何在工厂机器人上做到这一点。不要从文档中得到,所以希望能得到帮助。谢谢!

    以下是我的问题模型:

    class Question < ApplicationRecord
    
      belongs_to :question_status
      belongs_to :user
      has_many :choices
    
        accepts_nested_attributes_for :choices, limit: 5
    
      validates :content, :source, :year, presence: true
      validate :check_number_of_choices,
    
    
      def check_number_of_choices
        if self.choices.size != 5
            self.errors.add :choices, I18n.t("errors.messages.number_of_choices")
        end
      end
    
    end
    

    我的选择模型:

    class Choice < ApplicationRecord
    
      belongs_to :question
    
      validates :content, presence: true, allow_blank: false
    
    
    end
    

    我的工厂代码:

    FactoryBot.define do
    
        factory :question_status do
            name "Pending"
        end
    
      factory :choice do
        sequence(:content) { |n| "choice #{n}" }
        question
      end
    
    
      factory :question do
        sequence(:content) { |n| "question #{n}" }
        source "BBC"
        year "1999"
        user
        question_status
    
            before :create do |question|
            create_list :choice, 5, question: question
        end
    
      end
    
    end 
    

    以及我的特性测试(它仍然不起作用,但由于我的验证,它已经不能创建问题了):

    require 'rails_helper'
    
    RSpec.feature "Evaluating Questions" do
    
        before do
            puts "before"
            @john = FactoryBot.create(:user)
            login_as(@john, :scope => :user)
            @questions = FactoryBot.create_list(:question, 5)
            visit questions_path
        end
    
    
        scenario "A user evaluates a question correctly" do
            puts "scenario"
        end
    
    
    end
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Thomas Walpole    6 年前

    这里可能发生的事情是 select choices 集合代理导致Rails在验证期间再次尝试从数据库加载集合,但尚未持久化。尝试删除 选择 从您的验证

    if self.choices.size != 5
    

    这个 选择 可能根本不需要,因为 Choice 模型已经验证内容必须存在。在构建列表时,您可能还需要为问题分配选项。

    before :create do |question|
      question.choices = build_list :choice, 5, question: question
    end