Ruby on rails 与RSpec/FactoryGirl建立嵌套关联的最佳方法

Ruby on rails 与RSpec/FactoryGirl建立嵌套关联的最佳方法,ruby-on-rails,rspec,factory-bot,Ruby On Rails,Rspec,Factory Bot,我正在尝试为Rails应用程序构建一个测试套件,但我不确定如何使用FactoryGirl构建对象(如果需要,我可以使用其他工具) 棘手的部分是存在深层嵌套关联,让我们以模式的这一部分为例: 假设我想在“ItemTracker”模型上做一些测试。现在有两种方法: 为了有一个有效的对象,我需要建立一个连接,它需要一个令牌,它需要一个项目,等等。。。此外,我希望ProjectItem的项目与Token的项目相同。公司(在顶部)也是如此。我不想创建两个不同的项目或公司。所以我需要一种方法让这些对象共享

我正在尝试为Rails应用程序构建一个测试套件,但我不确定如何使用FactoryGirl构建对象(如果需要,我可以使用其他工具)

棘手的部分是存在深层嵌套关联,让我们以模式的这一部分为例:

假设我想在“ItemTracker”模型上做一些测试。现在有两种方法:

  • 为了有一个有效的对象,我需要建立一个连接,它需要一个令牌,它需要一个项目,等等。。。此外,我希望ProjectItem的项目与Token的项目相同。公司(在顶部)也是如此。我不想创建两个不同的项目或公司。所以我需要一种方法让这些对象共享一些关联。这种方法的一个缺点是,我不知道如何确保不创建多个关联对象,而且我还将构建大量不一定需要的对象(验证除外)

  • 我可以说“对于这个特殊的测试,关联是不相关的,所以我只需要创建一个ItemTracker,没有它的连接或投影项,用这个孤立的对象来做我的事情”。一般来说,我只需要创建实际需要的对象和关联。通过玩弄特质,我找到了一种方法,如果我不需要它们,可以避免产生联想。缺点是这个对象无效(关联上有验证),所以每次我试图在它上保存一些东西时,我都会遇到一个异常,这在一些测试用例中是一个难题

所以我想我的问题是:在这种复杂的对象结构中,设置一些测试对象的最佳方法是什么


感谢您的反馈;)

无论如何,您都需要构建整个关系树,但您可以将其放入一个trait中,例如,在specs中,使用trait
和所有关系创建项目跟踪器。它看起来是这样的:

FactoryGirl.define do
  factory :item_tracker do
    ...
    trait :with_all_relations do
      after(:build) do |item_tracker|
        company = create(:company)
        item = create(:item, company: company)
        user = create(:user, company: company)
        ...
        item_tracker.project_item = project_item
        item_tracker.connexion = connexion
      end
    end
  end
end
如果你没有指定任何特征,你会得到没有任何相关模型的物品跟踪器

我希望ProjectItem的项目与Token的项目相同 项目公司(在顶部)也是如此。我不想有两个 创建不同的项目或公司

通过使用
覆盖
初始化\u,可以使用“命名”工厂:

factory :project do
  # define common attributes for projects

  factory :project_1 do
    initialize_with do
      Project.find_or_create_by(name: "Project 1")
    end
  end
end
现在,您可以通过关联添加:

association :project, factory: project_1
并在不同模型的关联中获得相同的项目

请注意,这气味有点像夹具,所以你可以考虑夹具是否比工厂对你的情况更好。

我只需要创建我真正需要的对象和关联。通过玩弄特质,我找到了一种方法,如果我不需要它们,可以避免产生联想。缺点是此对象无效

我建议为每个工厂创建一个“基本”版本,只允许您设置属性,而无需关联,即使这是无效的。然后通过添加关联来扩展它以创建有效(可能无效)的版本。这是一个很好的例子