AssertionError,尽管预期调用与实际调用相同

6 投票
1 回答
3471 浏览
提问于 2025-04-18 15:02

我在Django里写了一个命令,这个命令会调用一个函数。

这个函数会进行一个Django的ORM调用:

def get_notes():
    notes = Note.objects.filter(number=2, new=1)
    return [x.note for x in notes]

我想要修改这个查找的具体实现:

@mock.patch('Note.objects.filter', autospec=True)
def test_get_all_notes(self, notes_mock):
    get_notes()
    notes_mock.assert_called_once_with(number=2, new=1)

但是我遇到了一个断言错误:

AssertionError: Expected call: filter(number=2, new=1)
Actual call: filter(number=2, new=1)

我在谷歌和StackOverflow上搜索了好几个小时,但还是没有头绪。有没有人能给我指个方向?我觉得我可能犯了一个很明显的错误……

1 个回答

2

据我所知,你不能这样使用 patch()。补丁的目标应该是一个字符串,格式是 package.module.ClassName。我对 Django 了解不多,但我猜 Note 是一个类,所以 Note.objects.filter 不是你可以直接导入的东西,因此也不能在 patch() 中使用。此外,我觉得 patch() 可能无法处理属性。实际上,我也不太明白为什么补丁能正常工作。

你可以试试使用 patch.object(),这是专门用来修补类属性的。它的意思是 Note 已经在你的测试模块中被导入了。

@mock.patch.object(Note, 'objects')
def test_get_all_notes(self, objects_mock):
    get_notes()
    objects_mock.filter.assert_called_once_with(number=2, new=1)

我把 autospec 去掉了,因为我不确定在这种情况下它是否能正常工作。如果可以的话,你可以试着再加上。

另一个选择是对 type(Note.objects) 的结果使用 patch()(这可能是某个 Django 类)。

正如我所说,我对 Django 了解不多,所以不确定这些方法是否有效。

撰写回答