Django 测试用例数据库给出不一致的响应、缓存或事务罪魁祸首?

and*_*ndy 4 django caching unit-testing transactions

我在 Django 测试中看到了一些非常令人惊讶和令人沮丧的行为。相关查找正在“找到”模型对象,但不存在模型对象。(我对这里奇怪的描述表示歉意……这种行为太奇怪了,我不知道如何描述它。这些物体存在吗?我存在吗?你存在吗??)

我需要它们存在,所以我有一个方法可以在它们不存在时创建它们。问题是,在一行中,Django 发现它们确实存在,因此它们没有被创建......然后在下一行我们可以确认不存在这样的对象。

我的测试在 test_something() 中给出了与缺少必要的 TaskMetadata 对象相关的错误。

#the model
class TaskMetadata(models.Model):
    task = models.OneToOneField(ContentType)
    ...

#the test
class SimpleTest(TestCase):
    def setUp(self):
        some_utility_function()

    def test_something(self):
        ...something that requires TaskMetadata...

def some_utility_function():
    task = ...whatever...
    ctype = ContentType.objects.get_for_model(task)
    try:
        ctype.taskmetadata
    except TaskMetadata.DoesNotExist:
        ...create TaskMetadata...
        print "Created TaskMetadata object for %s" % task.__name__
    else:
        print "TaskMetadata object already exists for %s" % task.__name__
        print ctype.taskmetadata
        print "ALL OF THEM!! %s" % TaskMetadata.objects.all()
Run Code Online (Sandbox Code Playgroud)

以及 some_utility_function() 的打印结果:

TaskMetadata object already exists for SomeTask
some task
ALL OF THEM!! []     # <-- NOTE EMPTY QUERYSET
Run Code Online (Sandbox Code Playgroud)

总之:“是的,TaskMetadata对象存在。是的,TaskMetadata对象存在。不,根本不存在TaskMetadata对象!!”

那么,说真的,这里到底发生了什么?这是缓存问题吗?我尝试清除缓存(大胆猜测;我没有在 settings.py 中配置缓存)

def setUp(self):
    cache.clear()
    some_utility_function()
Run Code Online (Sandbox Code Playgroud)

没有帮助。也许是交易?我很困惑。我该如何调试这个?

更新:请参阅复制 问题的最小 django 项目。

当第一个测试用例运行时,TaskMetadata.objects.all() 不是一个空查询集(它实际上填充了对象,正如我所期望的那样);当第二个测试用例(与第一个测试用例完全相同)运行时,它是空的。

我怀疑这与清除 TaskMetadata 对象的测试用例之间的数据库刷新有关,但相关的查找被缓存,因此下次为下一个测试用例调用 some_utility_function() 时,它不会创建任何 TaskMetadata 对象。1)这合理吗?2)如何解决这个问题?3)这是一个 Django 错误,对吧?

Django 错误票

mjt*_*lyn 5

在您的tearDown方法中,您需要调用ContentType.objects.clear_cache()。这是因为 Django 缓存了对ContentType.objects.get_for_model. 一对一的内容类型有点奇怪,所以我认为 django 不需要为此进行任何更改,特别是因为它应该是一行修复。