如何使Django单元测试检查M2M数据库约束?

时间:2019-03-15 15:41:18

标签: django django-models

说我有这个模型定义:

class Foo(Model):
   ...

class Bar(Model):
   some_m2m_field = ManyToManyField(Foo)

和此代码:

bar = Bar.objects.create()
bar.some_m2m_field.set(an_id_array_with_some_invalid_pks)

当我正常运行该命令时,最后一行将按其应该抛出IntegrityError。但是,如果我从django.test.TestCase运行相同的代码,则最后一行不会引发错误。相反,它将等到测试的_post_teardown()阶段抛出IntegrityError

这是一个演示问题的小项目:https://github.com/t-evans/m2mtest

该如何解决?我想这是可配置的,但是我找不到它...

后续问题:

最终,我需要处理将错误的ID传递给m2m_field.set()方法的情况(并且我需要进行单元测试以验证错误的ID是否得到正确处理,这就是为什么延迟的{{1 }}在单元测试中将无效。

我知道我可以通过遍历数组并为每个ID击中一个DB来找到错误的ID。是否有更有效的方法来查找错误的ID,或者(更好)只是告诉IntegrityError方法忽略/删除错误的ID?

2 个答案:

答案 0 :(得分:1)

有关如何解决单元测试问题,请参见@dirkgroten的答案。

关于如何更有效地消除不良ID的后续问题,一种方法如下:

good_ids = Foo.objects.filter(id__in=an_id_array_with_some_invalid_ids).values_list('id', flat=True)

答案 1 :(得分:1)

TestCase相比,

atomic()将测试包装在其他TransactionTestCase块中,因此要测试特定的数据库事务行为,应使用TransactionTestCase

我相信IntegrityError仅在提交事务时才抛出,因为那是数据库发现丢失id的那一刻。

通常,如果要测试测试期间引发的数据库异常,则应使用TransactionTestCase并使用以下代码测试代码:

with self.assertRaises(IntegrityError):
     # do something that gets committed to db