Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to set up nested associations with RSpec / FactoryGirl

I am trying to build a test suite for a Rails app, and I'm not sure how to build objects with FactoryGirl (I can move to a different tool if necessary).

The tricky part is that there are have deep nested associations, lets take for example this part of the schema : http://imgur.com/HAUS7kr

Let's say I want to do some tests on the "ItemTracker" model. Now there are 2 approaches :

  • In order to have a valid object, I will need to build a Connexion, which needs a Token, which needs a Project, etc... Also, I want the ProjectItem's project to be the same as the Token's project. Same thing with Company (on top). I wouldn't want to have 2 different projects or companies created. So I need a way for these objects to share some associations. One drawback of this approach is that I'm not sure how to make not created several associated objects, and I'm also gonna build a ton of objects I don't necessarily need (except for validations)

  • I could say "for this particular test, the associations are irrelevant, so I'm just gonna create one ItemTracker, without its Connexion or ProjectItem, and do my things with this isolated object". In a general manner, I would just create the objects and associations I actually need. By playing with traits, I found a way to avoid creating the associations if I don't need them. The drawback is that this object will not be valid (there are validations on associations), so every time I'm gonna try to save something on it, I'm gonna have an Exception, which will be a pain in some test cases.

So I guess my question is : what is the best way to set up some objects for testing in this kind of complex object structure ?

Thanks for the feedback ;)

like image 444
BPruvost Avatar asked Oct 18 '22 20:10

BPruvost


1 Answers

You need to build this whole relation tree anyway, but you can put this into a trait and, in specs, create item tracker with trait with_all_relations, for example. It would look like this:

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

And if you specify no trait, you'll get item tracker without any related models.

like image 63
Jeiwan Avatar answered Oct 29 '22 23:10

Jeiwan