你能在FactoryGirl中明确输入方法的返回值吗?

时间:2016-11-21 00:37:50

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

假设我有以下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测试此方法时,是否可以直接使用Employee属性设置total_annual_income工厂而无需创建相应的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的新手,如果我忽略了一些基本的东西,请道歉。

1 个答案:

答案 0 :(得分:0)

查看Factory Girl文档下的协会信息:

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

这是一个:user_with_posts示例,它使用#create_list为用户生成帖子列表 - 有点像您的工作列表。因为在StackOverflow上,习惯上包括完整的答案,以防外部链接被破坏,这里的示例的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方法。

[编辑] 完全未经测试,我认为你的例子就像:

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.

...或多或少。