Brandt Solovij Brandt Solovij - 6 months ago 11
Ruby Question

FactoryGirl `factory define` pattern for a 'Factory' class which creates n number of Class types

I'm going to be as brief as possible, please assume that completely rewriting what im about to describe is imminent however

not on this sprint


Given there is a factory class like (pseudo):

class AFactory

....
def self.distribute_types(args)
case args[:type]
when A
return ClassOfTypeA.new(args)
when B
return ClassOfTypeB.new(args)
when C
return ClassOfTypeC.new(args)
else
return ClassNamedSue(args)
end
end
end


I need to write FactoryGirl traits for this "factory" class but i cant find examples of how to properly use /other/ factories which represent the class(es) which would be built, depending.


edit: Please note, disregard the actual
AFactory
pattern - it is
known as suspect and will be properly redistributed along healthy
guidelines later on. Please do not spend time considering it's
wonky-ness and instead, focus on how to properly test this -- each
generated class instance, has a factory already dedicated to it, and I
would like to utilize those in this
AFactory
test.


How to include a factory within another factory - is the abject question i suppose.

Answer

I see no value in using FactoryGirl for this class. Its only method is one that will generate an instance of a class if given the right arguments.

The more ideal approach would be to set up N cases - N representing the number of possible values args[:type] could take - and test that way. You know what you're expecting when you feed the right type to this class, so there's little reason to include FactoryGirl for this test at all.

Here's a rough RSpec skeleton. You're not testing anything other than the fact that your factory gave you the type you wanted (and also you'll want to test that it added the values you expected, but I leave that as an exercise for the reader).

describe AFactory do
  context 'when args[:type] is A' do
    let(:args) {
      {type: A}
    }

    it 'returns the right instance' do
      result = AFactory.distribute_types(args)
      # verify here
    end
  end

  context 'when args[:type] is B' do
    let(:args) {
      {type: B}
    }

    it 'returns the right instance' do
      result = AFactory.distribute_types(args)
      # verify here
    end
  end

  context 'when args[:type] is C' do
    let(:args) {
      {type: C}
    }

    it 'returns the right instance' do
      result = AFactory.distribute_types(args)
      # verify here
    end
  end

  context 'when args[:type] is any other value' do
    let(:args) {
      {type: 'foo bar baz bing boof'}
    }

    it 'returns the right instance' do
      result = AFactory.distribute_types(args)
      # verify here
    end
  end
end
Comments