I'm writing unit tests for a Django app which use factory_boy
test fixtures. In some cases, one fixture might try to create an object that was already created by another fixture, which leads to error messages similar to the following:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "lucy_web_sessiontype_title_c207e4f8_uniq"
DETAIL: Key (title)=(Postpartum Doula Support) already exists.
To avoid this, my first inclination is to write a try..except
block, like so:
try:
SessionTypeFactory(title='Welcome')
except psycopg2.IntegrityError as e:
pass
However, it seems like it would be more elegant to use the django_get_or_create
option described at http://factoryboy.readthedocs.io/en/latest/orms.html#factory.django.DjangoOptions.django_get_or_create.
However, as far as I can tell from http://factoryboy.readthedocs.io/en/latest/reference.html#factory.FactoryOptions, options specifie in the factory's Meta
class will apply to all instances, whereas I would only like it to only apply to this instance. Is it possible to specify these options in the constructor?
The doc is slightly misleading. What is documented in the FactoryOptions
section is the list of options available in the class Meta
part.
In your case, you could go with the following code sample:
class SessionTypeFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.SessionType
django_get_or_create = ['title']
# your fields here
This will perform a SessionType.objects.get_or_create(title=fields.pop('title'), defaults=fields)
every time you create an instance.
Since you have a unique
condition on the title
field, you can safely put that behavior in place at the SessionTypeFactory
level.