New version of factory_boy does not work with a simple RelatedFactory case
See original GitHub issueHi all, I upgraded to factory_boy 2.9.1 and a bunch of my tests are failing. I’ve isolated it down to a simple set of models. This was modeled on the documentation.
import factory
from django.db import models
from django.contrib.auth.models import User
from base.models import Account, Profile
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
# We pass in 'user' to link the generated Profile to our just-generated
# User. This will call ProfileFactory(user=our_new_user), thus
# skipping the SubFactory.
profile = factory.RelatedFactory(
'base.tests.factories.broken_factories.ProfileFactory', 'user')
username = factory.Sequence(lambda n: 'user.username%d' % n)
class AccountFactory(factory.django.DjangoModelFactory):
class Meta:
model = Account
admin = factory.SubFactory(UserFactory)
name = factory.SelfAttribute('admin.email')
class ProfileFactory(factory.django.DjangoModelFactory):
class Meta:
model = Profile
# We pass in None to prevent UserFactory from creating another
# profile (this disables the RelatedFactory)
user = factory.SubFactory(UserFactory, profile=None)
In my base.models
, Account
and Profile
look like this, roughly:
class Account(models.Model):
admin = models.ForeignKey(User, related_name='account_admin')
name = models.CharField(max_length=64)
class Profile(models.Model):
user = models.OneToOneField(User)
This fails in my tests when I instantiate AccountFactory()
with no arguments. This is the error traceback and messaging:
DEBUG 2017-08-03 18:03:29,012 [factory.generate] [declarations.py::generate:392 ] SubFactory: Instantiating base.tests.factories.broken_factories.UserFactory(), create=<factory.builder.BuildStep object at 0x7faf4ef4bf50>
DEBUG 2017-08-03 18:03:29,012 [factory.generate] [declarations.py::evaluate:206 ] Sequence: Computing next value of <function <lambda> at 0x7faf54f447d0> for seq=0
DEBUG 2017-08-03 18:03:29,015 [factory.generate] [declarations.py::call:615 ] RelatedFactory: Generating base.tests.factories.broken_factories.ProfileFactory(<factory.builder.BuildStep object at 0x7faf4f9e3110>, user=<User: user.username0>)
DEBUG 2017-08-03 18:03:29,015 [factory.generate] [declarations.py::evaluate:58 ] LazyFunction: Evaluating <built-in function time> on <factory.builder.BuildStep object at 0x7faf4f76b410>
E
======================================================================
ERROR: test_broken_factory (base.tests.test_factories.FactoryTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/app/djapp/base/tests/test_factories.py", line 51, in test_broken_factory
AccountFactory()
File "/usr/local/lib/python2.7/site-packages/factory/base.py", line 46, in __call__
return cls.create(**kwargs)
File "/usr/local/lib/python2.7/site-packages/factory/base.py", line 568, in create
return cls._generate(enums.CREATE_STRATEGY, kwargs)
File "/usr/local/lib/python2.7/site-packages/factory/base.py", line 505, in _generate
return step.build()
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 272, in build
step.resolve(pre)
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 221, in resolve
self.attributes[field_name] = getattr(self.stub, field_name)
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 363, in __getattr__
extra=declaration.context,
File "/usr/local/lib/python2.7/site-packages/factory/declarations.py", line 306, in evaluate
return self.generate(step, defaults)
File "/usr/local/lib/python2.7/site-packages/factory/declarations.py", line 395, in generate
return step.recurse(subfactory, params, force_sequence=force_sequence)
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 233, in recurse
return builder.build(parent_step=self, force_sequence=force_sequence)
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 293, in build
context=postgen_context,
File "/usr/local/lib/python2.7/site-packages/factory/declarations.py", line 617, in call
return step.recurse(factory, passed_kwargs)
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 233, in recurse
return builder.build(parent_step=self, force_sequence=force_sequence)
File "/usr/local/lib/python2.7/site-packages/factory/builder.py", line 279, in build
kwargs=kwargs,
File "/usr/local/lib/python2.7/site-packages/factory/base.py", line 314, in instantiate
return self.factory._create(model, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/factory/django.py", line 165, in _create
return manager.create(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 394, in create
obj.save(force_insert=True, using=self.db)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 807, in save
force_update=force_update, update_fields=update_fields)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 837, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 923, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 962, in _do_insert
using=using, raw=raw)
File "/usr/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/django/db/models/query.py", line 1076, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/usr/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1107, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 101, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 174, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
IntegrityError: (1062, "Duplicate entry '1' for key 'user_id'")
Issue Analytics
- State:
- Created 6 years ago
- Comments:11 (6 by maintainers)
Top Results From Across the Web
Common recipes — Factory Boy stable documentation
Simple Many-to-many relationship . Building the adequate link between two models depends heavily on the use case; factory_boy doesn't provide a “all...
Read more >Django, Factory boy - can't create subfactory - Stack Overflow
I have solved the problem to create a label first you need to create a profile profile = ProfileFactory.create().
Read more >pytest-factoryboy - Python Package Health Analysis - Snyk
Latest version published 5 months ago. License: MIT ... No known security issues. popularity ... Looks like pytest-factoryboy is missing a security policy....
Read more >Factory Boy Documentation - Read the Docs
Factory Boy Documentation, Release 1.3.0 ... handles such cases: it should receive a function taking the ... Simple build, do nothing.
Read more >Testing Models with Django using Faker and Factory Boy
The factory_boy library(modeled after Factory Girl in Rails) the generation of data for tests. In Django, data for tests was called fixtures, ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
2.8.1 worked, and 2.9/2.9.1 don’t work with my code.
I’m closing this issue for now, since it seems to be due to an internals refactor messing up with an private-yet-slightly-documented method.
Please reopen it if the bug is still out there, or if the documentation fixes aren’t sufficient!