Django Mock未按预期工作:单元测试方法调用断言失败求助
嘿,我之前踩过好几次Django Mock断言失败的坑,咱们一步步来排查解决你的问题:
先解决你最直接的需求:只想验证方法被调用过(不管参数)
如果你不需要校验具体参数,只是想确认make_reset_password被调用了一次,那别用assert_called_once_with(user)——这个方法会严格匹配参数是否完全一致。直接换成:
mocked.assert_called_once()
就能达到你要的效果啦。
如果你的本意是要校验参数确实是这个user对象,那大概率是这两个问题:
1. Mock的路径写错了(最常见的坑!)
Django里Mock的路径特别讲究,你要patch的是被测试代码实际导入并使用的那个路径,而不是方法定义的原始模块路径。举个例子:
- 假设你的业务代码(比如
views.py)里是这么导入的:from myapp.utils import make_reset_password - 那你应该patch的是
myapp.views.make_reset_password,而不是utils.make_reset_password
简单说:patch的是方法被使用的模块里的引用,不是方法定义的模块。你去检查下业务代码里的导入方式,调整patch的路径就好。
2. 参数对象不匹配
有时候User.get(...)返回的对象,和你传递给方法的对象,在Mock断言时会被判定为不同实例(比如ORM对象的某些场景)。这种情况可以用Mock的参数匹配器来宽松校验:
from unittest.mock import ANY # 匹配任意参数 mocked.assert_called_once_with(ANY) # 或者匹配User类型的对象 from unittest.mock import instance_of mocked.assert_called_once_with(instance_of(User))
另外,你可以在断言前打印实际调用的参数,方便对比排查:
print(mocked.call_args) # 会输出类似call(<User object at 0x...>)的内容,看看和你预期的user是不是同一个
给你调整后的测试示例参考
from unittest.mock import patch, ANY from django.test import TestCase from myapp.models import User from myapp.utils import make_reset_password class MyTestCase(TestCase): # 注意这里的路径要和业务代码的导入一致 @patch('myapp.views.make_reset_password') def test_shouldHaveCalledMakeResetToken(self, mocked): user = User.objects.get(...) # 假设用ORM的get方法 make_reset_password(user) # 不需要校验参数的情况 mocked.assert_called_once() # 宽松匹配参数的情况 # mocked.assert_called_once_with(ANY) # 路径正确且需要严格匹配参数的情况 # mocked.assert_called_once_with(user)
内容的提问来源于stack exchange,提问作者FVod
相关产品推荐
相关产品推荐

