【问题标题】:Can you explicitly enter a method's return value in FactoryGirl?你能在 FactoryGirl 中显式输入方法的返回值吗?
【发布时间】:2016-11-21 00:37:50
【问题描述】:

假设我有以下 Rails 模型并且显示的方法已经过测试。

class Employee < ActiveRecord::Base
  has_many :jobs

  def total_annual_income
    jobs.collect { |j| j.annual_salary}.sum
    # Or some other AR magic to do it directly in the database; doesn't matter
  end
end

class Job < ActiveRecord::Base
  # property :annual_salary

  belongs_to :employee
end

现在,假设我要在别处编写调用Employee#total_annual_income 的其他方法。当我使用 FactoryGirl 测试此方法时,是否可以直接使用 total_annual_income 属性设置我的 Employee 工厂,而无需创建相应的 Job 工厂?即,我可以简单地做吗

FactoryGirl.define do
  factory :employee1, class: Employee do
    id 100
    total_annual_income 100000.0
  end
end

而不是

FactoryGirl.define do
  factory :employee1, class: Employee do
    id 100
  end
end

# WANT TO OMIT THIS ENTIRE SET OF FACTORIES #
FactoryGirl.define do
  factory :employee1_job1, class: Job do
    id 100
    employee_id 100
    annual_salary 60000.0
  end
  factory :employee1_job2, class: Job do
    id 101
    employee_id 100
    annual_salary 40000.0
  end
end
# WANT TO OMIT THIS ENTIRE SET OF FACTORIES #

我对 FactoryGirl 还是有点陌生​​,所以如果我忽略了一些基本的东西,我深表歉意。

【问题讨论】:

    标签: ruby-on-rails unit-testing factory-bot


    【解决方案1】:

    查看 Factory Girl 文档下的关联信息:

    https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#associations

    这有一个:user_with_posts 的示例,它使用#create_list 为用户生成帖子列表——有点像你的工作列表。由于在 StackOverflow 上通常会包含完整的答案,以防外部链接损坏,这里是带有 cmets 的示例的 copypasta:

    为 has_many 关系生成数据有点复杂,具体取决于所需的灵活性,但这里有一个生成关联数据的可靠示例。

    FactoryGirl.define do
    
      # post factory with a `belongs_to` association for the user
      factory :post do
        title "Through the Looking Glass"
        user
      end
    
      # user factory without associated posts
      factory :user do
        name "John Doe"
    
        # user_with_posts will create post data after the user has been created
        factory :user_with_posts do
          # posts_count is declared as a transient attribute and available in
          # attributes on the factory, as well as the callback via the evaluator
          transient do
            posts_count 5
          end
    
          # the after(:create) yields two values; the user instance itself and the
          # evaluator, which stores all values from the factory, including transient
          # attributes; `create_list`'s second argument is the number of records
          # to create and we make sure the user is associated properly to the post
          after(:create) do |user, evaluator|
            create_list(:post, evaluator.posts_count, user: user)
          end
        end
      end
    end
    

    这让我们可以这样做:

    create(:user).posts.length # 0
    create(:user_with_posts).posts.length # 5
    create(:user_with_posts, posts_count: 15).posts.length # 15
    

    这其中的核心其实就是上面显示的#create_list方法。

    [EDIT] 完全未经测试,我认为您的示例如下:

    FactoryGirl.define do
      factory :employee_with_jobs, class: Employee do
        id 100
    
        transient do
          jobs_count 2
        end
    
        after(:create) do |employee, evaluator|
          create_list(:job, evaluator.jobs_count,
                      employee: employee,
                      annual_salary: 40000.0)
        end
      end
    end
    
    create(:employee_with_jobs, jobs_count: 5) # Expecting total salary 200000.0.
    

    ...或多或少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 2020-09-28
      • 2018-08-23
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      相关资源
      最近更新 更多