有可能问工厂女孩给定工厂有哪些关联?

时间:2011-04-11 13:40:33

标签: ruby unit-testing factory-bot

Factory Girl对于功能测试非常有用,但是有一个恼人的属性使得在单元测试中使用起来稍微困难一些,我不想依赖测试数据库。我经常使用Factory.build创建一个工厂,然后我可以使用flexmock传递或分配到ActiveRecord.find来电:

require 'test_helper'
require 'flexmock'

class SomeMixinTest < ActiveSupport::TestCase
  include FlexMock::TestCase

  def setup
    @foo = Factory.build(:foo, :id => 123,
        :bar => Factory.build(:bar, :id => 456,
            :baz => Factory.build(:baz, :id => 789)
        )
    )

    flexmock Foo, :find => @foo
  end

  def test_find_by_reverse_id
    assert_equal @foo, Foo.find_by_reverse_id(321)
  end
end

这种模式非常好,因为它不关心数据库的存在,并且运行速度比实际持久化对象要快得多。但是,必须手动构建关联对象有点烦人。如果不这样做,则build调用实际上会在数据库中创建关联对象 ,就像您使用了create一样。

assert_equal [], Foo.all
foo = Factory.build :foo  # build my associations too, please
assert_equal [], Foo.all  # look Ma, no mocks!
assert_equal [], Bar.all  # <=== ASSERTION FAILED
assert_equal [], Baz.all

这至少可以说是非直观的,当我测试一些需要与mixin很好地合作的类时,会导致实际问题。我希望能够做到这一点:

  KLASSES_UNDER_TEST = [Foo, Bar, Baz]

  def test_find_by_reverse_id
    KLASSES_UNDER_TEST.each do |klass|
      objects = (123..456).map do |id|
        Factory.build klass.to_s.downcase.to_sym, :id => id
      end

      flexmock klass, :all => objects

      objects.each do |object|
        assert_equal object, klass.find_by_reverse_id(object.id.to_s.reverse), "#{klass} #{object.id}"
    end
  end

但这会产生令人讨厌的副作用,即在数据库中创建333 Bar和666 Baz es(“Baz”听起来有点像恶魔的昵称,所以可能是合适的)这个测试比冬天上流的糖蜜慢。

我想创建一个这样的辅助方法:

  def setup_mocks(klass)
    klass_sym = klass.to_s.downcase.to_sym
    objects = (123..456).map{|id|
      associated_objects = Hash[
        Factory.associations(klass_sym).map do |association|
          [ association, setup_mocks(association, 1) ]
        end
      ]

      Factory.build klass_sym, associated_objects
    end

    flexmock klass, :all => objects
    objects
  end

那么,Factory.associations之类的东西是否存在?

1 个答案:

答案 0 :(得分:0)

我没有对此进行过测试,但是看一下这个来源似乎应该有效:

FactoryGirl.find(:factory_name).associations