R – DRYer tests with associations in factory_girl

factoryfactory-botfunctional-testingruby-on-railstesting

Can anyone suggest a better way to make a factory use a pre-built model
instance for its association? For example, so that it would be possible
below to define a child of the Message factory so that a call to
Factory(:my_message) could substitute for
Factory(:message,:sender=>@me) ?

Sometimes the setup hash is more involved than in this contrived
example, or is just repeated in so many tests that it would seem better to push it down into the factory.

One alternative I can think of is to define a test helper method
such as create_message_owned_by(@me), but I'm hoping there's a way within factory_girl itself.

factory_girl factories:

Factory.define :sender do |s|
  sender.name "Dummy name"
end

Factory.define :message do |msg|
  msg.text "Dummy text"
  msg.association :sender
end

Factory.define :my_message, :parent=>:message do |msg|
  msg.text "Dummy text"
  ### ? what goes here for msg.association :sender ? ###
end

MessagesControllerTest excerpt (using shoulda):

context "on GET /messages" do
  setup do
    @me = Factory(:sender)
    @my_message = Factory(:message,:sender=>@me)
    @somebody_elses_message = Factory(:message)
    sign_in_as(@me)
    get :index
  end
  should "only assign my messages" do
    assert_contains(assigns(:messages), @my_message)
    assert_does_not_contain(assigns(:messages), @somebody_elses_message)
  end
end

Best Answer

I don't know if this is what you're looking for, but if you first create message you can fetch the sender through that and assign it to @me.

@my_message = Factory(:message)
@me = @my_message.sender

Does that help at all?