James Lin
James Lin

Reputation: 26538

Django unittest gives `Cannot add or update a child row: a foreign key constraint fails`

I have 3 different apps and each of them has unittest, if I run

python manage.py test categories coupons stores

I would get

IntegrityError(1452, 'Cannot add or update a child row: a foreign key constraint fails (`test_gocoupons`.`coupons_coupon`, CONSTRAINT `store_id_refs_id_bf6c0d9e` FOREIGN KEY (`store_id`) REFERENCES `stores_store` (`id`))'))

However if I run them individually they are fine.

This is a test mixin that all test cases uses:

# G is a function to create fixtures see django-dynamic-fixtures

class GoCouponsTestCaseMixin(object):
    categories = []
    stores = []
    coupons = []
    offers = []

    def setUp(self):
        self.categories.append(G(Category))
        self.stores.append(G(Store, is_active=True))
        # make sure we generate enough coupons for page 2
        for i in range(1, settings.COUPON_PAGE_SIZE + 10):
            coupon = G(Coupon, title='free', store=self.stores[0], is_active=True)
            CouponCategory.objects.create(coupon=coupon, category=self.categories[0])
            Offer.objects.create(start=timezone.now() + timedelta(days=-10), expire=timezone.now() + timedelta(days=10), coupon=coupon)
            self.coupons.append(coupon)

Stacktrace show this line is causing the problem:

coupon = G(Coupon, title='free', store=self.stores[0], is_active=True)

Upvotes: 1

Views: 799

Answers (1)

James Lin
James Lin

Reputation: 26538

Looks like it's caused by django-dynamic-fixtures, adding a couple of queries to get the object looks like made it to commit the insert queries.

class GoCouponsTestCaseMixin(object):
    categories = []
    stores = []
    coupons = []
    offers = []

    def setUp(self):
        self.categories.append(G(Category))
        self.stores.append(G(Store, is_active=True))

        # manually querying the objects fixed it
        store = Store.objects.first()
        category = Category.objects.first()

        # make sure we generate enough coupons for page 2
        for i in range(1, settings.COUPON_PAGE_SIZE + 10):
            coupon = G(Coupon, title='free', store=store, is_active=True)
            CouponCategory.objects.create(coupon=coupon, category=category)
            Offer.objects.create(start=timezone.now() + timedelta(days=-10), expire=timezone.now() + timedelta(days=10), coupon=coupon)
            self.coupons.append(coupon)

Upvotes: 1

Related Questions