说我有这个模型定义:
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?
答案 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