You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用Mock对象的Python/Django单元测试无法正常运行?

嘿,我看到你在Django模型的Mock测试上踩坑了,咱们来捋清楚问题出在哪:

核心问题:混淆了Mock类和Mock实例

你现在的测试失败,根源是错误地修改了Mock类对象的方法,而非类实例的方法:

  • 当你用@mock.patch('run.models.Book', autospec=True)装饰测试方法时,参数mock_book是Book类的Mock替身,不是具体的实例。
  • 调用Book()等价于调用mock_book(),会返回mock_book.return_value——这才是模拟出来的Book实例对象。
  • 你之前修改的mock_book.retrieve_isbn是类级别的方法,但实际调用的是实例的retrieve_isbn,所以你的Mock设置根本没作用到目标对象上,自然还是返回原方法的abc123。
修正后的测试代码
# tests.py
import unittest
from unittest import mock
from run.models import Book

class TestModel(unittest.TestCase):
    @mock.patch('run.models.Book', autospec=True)
    def test_book_isbn(self, mock_book):
        # 配置Mock实例的retrieve_isbn返回值
        mock_book_instance = mock_book.return_value
        mock_book_instance.retrieve_isbn.return_value = 'foo123'
        
        # 调用实例方法(此时Book()会返回我们配置好的Mock实例)
        isbn = Book().retrieve_isbn()
        
        # 断言结果
        self.assertEqual(isbn, 'foo123')
额外小提示
  • 你的测试用例里并没有用到Author的逻辑,完全可以去掉@mock.patch('run.models.Author'),减少不必要的Mock复杂度。
  • 用autospec=True是个好习惯,它会强制Mock遵循原类的结构,避免你设置不存在的属性/方法,但要注意:类属性和实例属性要区分开,比如你之前设置的mock_book.title是无效的,因为title是实例属性,不是类属性。
  • 还有一种等价的写法,直接给实例方法赋值MagicMock:
    mock_book.return_value.retrieve_isbn = mock.MagicMock(return_value='foo123')
    

内容的提问来源于stack exchange,提问作者Jim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:04:33