Search code examples
pythondjangounit-testingfactoryfactory-boy

Factory Boy and related objects creation


Let's say you have these Django models related this way:

class Service:
   restaurant = models.ForeignKey(Restaurant)
   hist_day_period = models.ForeignKey(DayPeriod)

class DayPeriod:
   restaurant = models.ForeignKey(Restaurant)

I want to create a Service object, using a Factory. It should create all 3 models but use the same restaurant.

Using this code:

class ServiceFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = Service

    restaurant = factory.SubFactory('restaurants.factories.RestaurantFactory')

    hist_day_period = factory.SubFactory(
        'day_periods.factories.DayPeriodFactory', restaurant=restaurant)

Factory boy will create 2 different restaurants:

s1 = ServiceFactory.create()
s1.restaurant == s1.hist_day_period.restaurant
>>> False

Any idea on how to do this? It's unclear to me if I should use related factors instead of SubFactory to accomplish this.


Solution

  • You want to use factoryboy's parents and SelfAttribute

    class ServiceFactory(factory.django.DjangoModelFactory):
        class Meta:
            model = Service
    
        restaurant = factory.SubFactory('restaurants.factories.RestaurantFactory')
    
        hist_day_period = factory.SubFactory(
            'day_periods.factories.DayPeriodFactory',
            restaurant=factory.SelfAttribute('..restaurant')
        )
    

    with this test app I get

    In [1]: from service.tests import ServiceFactory
    In [2]: s1 = ServiceFactory.create()
    In [3]: s1.restaurant == s1.hist_day_period.restaurant
    Out[3]: True
    
    In [4]: s1.restaurant_id
    Out[4]: 4
    
    In [5]: s1.hist_day_period.restaurant_id
    Out[5]: 4