0

我正在使用 RSpec 和 FactoryGirl 来测试我的 Ruby-on-Rails-3 应用程序。我正在使用工厂的层次结构:

FactoryGirl.define do
  factory :local_airport do

    ... attributes generic to a local airport

    factory :heathrow do
      name    "London Heathrow"
      iata    "LHR"
    end

    factory :stansted do
      name "Stansted"
      iata "STN"
    end

    ... more local airports
  end
end

在我的 RSpec 中,有时我希望能够通过指定父工厂来创建所有子工厂。理想情况下,类似:

describe Flight do
  before( :each ) do
    # Create the standard airports
    FactoryGirl.find( :local_airport ).create_child_factories
  end
end

提前谢谢了。

4

2 回答 2

0

经过几个小时研究 FactoryGirl 代码后,我找到了解决方案。有趣的是,FactoryGirl 仅在工厂中存储对父级的引用,而不是从父级到子级的引用。

在 spec/factories/factory_helper.rb 中:

module FactoryGirl
  def self.create_child_factories( parent_factory )
    FactoryGirl.factories.each do |f|
      parent = f.send( :parent )
      if !parent.is_a?(FactoryGirl::NullFactory) && parent.name == parent_factory
        child_factory = FactoryGirl.create( f.name )
      end
    end
  end
end

在我的 RSpec 中,我现在可以写:

require 'spec_helper'

describe Flight do
  before( :each ) do
    # Create the standard airports
    FactoryGirl.create_child_factories( :local_airport )
  end

  ...

我发现的一个问题是最好有一个简单的工厂层次结构(即两个级别)。我从三层层次结构开始,发现我正在生成仅作为层次结构的一部分存在的“抽象”工厂。我使用特征将层次结构简化为两个级别。

于 2013-07-14T18:25:38.500 回答
0

您不能真正告诉工厂构建它所有的子工厂,因为作为子工厂只是意味着它继承了父工厂的属性。但是你可以做的是添加一个特征,例如:with_child_factories. 然后您的工厂将如下所示:

    FactoryGirl.define do
      factory :local_airport do

        ... attributes generic to a local airport

        factory :heathrow do
          name    "London Heathrow"
          iata    "LHR"
        end

        factory :stansted do
          name "Stansted"
          iata "STN"
        end

        ... more local airports

        trait :with_child_factories do
          after(:create) do
            FactoryGirl.create(:heathrow)
            FactoryGirl.create(:stansted)
            ...
          end
        end
      end
    end

然后你可以在你的测试中调用它

        FactoryGirl.create(:local_airport, :with_child_factories)
于 2013-07-11T18:34:46.410 回答