Home > Blockchain >  Trying to test a nested serilailzer, how to create required subfactories?
Trying to test a nested serilailzer, how to create required subfactories?

Time:04-01

I am getting a failing test because (I think) I can't add a subfactory field.

I have a serializer that calls on another serializer. I am finding it difficult to replicate this in a test (specifically the factory). The issue is caused by my test: _expected_restuarant_response. It is expecting a response that includes an employee field (like the serializer does). The problem is that I can't add this subfactory field to RestaurantFactory because RestaurantFactory is located above EmployeeFactory in the factories.py file (EmployeeFactory has not yet been initialised at that point in the file). I also can't put EmployeeFactory higher than RestaurantFactory because it refers to RestaurantFactory.

Could somebody point me in the right direction? Thank you.

A simplified version of my files:

models.py:

class Restaurant(models.Model):
    name = models.CharField(max_length=20)

class Employee(models.Model):
    badge_id = models.CharField(max_length=20)
    restaurant = models.ForeignKey(Restaurant)

serializers.py:

class EmployeeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Employee
        fields = [
            'badge_id']

class RestaurantSerializer(serializers.ModelSerializer):
    employee = EmployeeSerializer(many=True, read_only=True)
    class Meta:
        model = Restaurant
        fields = [
            'name',
            'employee']

factories.py:

class RestaurantFactory(factory.django.DjangoModelFactory):
    name = factory.Faker('company')
         < ----------------------------------- do I need to add an Employee subfactory here? If so how?

class EmployeeFactory(factory.django.DjangoModelFactory):
    badge_id = factory.Faker('id')
    restaurant = factory.SubFactory(RestaurantFactory) 

test.py:

def _expected_restuarant_response(restaurant):
    return {
        restaurant.name,
        restaurant.employee_set.badge_id     <---- the test fails here because the RestaurantFactory does not include this field
         }

assert response_json == [_expected_restaurant_response(RestaurantFactory())]

CodePudding user response:

In terms of the Factory creation you could probably do something like this:

class RestaurantFactory(factory.django.DjangoModelFactory):
    name = factory.Faker('company')
    employee = factory.SubFactory('path.to.EmployeeFactory', employee=None)

then on EmployeeFactory do this:

class EmployeeFactory(factory.django.DjangoModelFactory):
    badge_id = factory.Faker('id')
    restaurant = factory.RelatedFactory(RestaurantFactory, factory_related_name='employee')
  • Related