Search code examples
pythondjangooptional-parametersfactory-boy

Django factoryboy fail when used as default parameter value


I have a set of factories that I run during the test stage through a convenient function called Create. When I need to reference an existing project, I pass it as parameters, if not I create a new one with FactoryBoy:

def Create(project=ProjectFactory()):
    # do stuff with project

I am calling the function like so:

Create() # new project will be defined
Create(existing_project) # existing project will be used

But it doesn't work, I have a bunch of errors:

E   ProgrammingError: relation "auth_user" does not exist
E   LINE 1: ...user"."is_active", "auth_user"."date_joined" FROM "auth_user...
E                                                                 ^

After trying for some days different workarounds, I found that this version works:

def Create(project=None):
    project = ProjectFactory() if not project else project
    # do stuff with project

For me it does the same thing, what am I missing here?


Solution

  • Note that the default argument in def Create(project=ProjectFactory()): is bound at module loading time, essentially when the test runner starts. Since the test runner migrates the test database from scratch, it cannot create and save a Project at that point.

    In the second version

    def Create(project=None):
        project = ProjectFactory() if not project else project
    

    The code that creates the Project is inside the function and is, thus, only executed once the function is called -- after the migrations ran.