python runtime_error ai_generated true

AssertionError: 期望 'send_email' 被调用一次。实际调用 0 次。

AssertionError: Expected 'send_email' to be called once. Called 0 times.

ID: python/mock-patch-wrong-target

其他格式: JSON · Markdown 中文 · English
80%修复率
89%置信度
0证据数
2024-01-19首次发现

版本兼容性

版本状态引入弃用备注
3.11 active — — —
3.12 active — — —

根因分析

unittest.mock.patch 打补丁的对象是函数定义所在的模块,但被测代码通过 from ... import 把该函数导入了自己的命名空间。补丁替换的是原始符号,而非已导入的引用。

English

unittest.mock.patch targeted the module where the function is defined, but the code under test imported it by name into its own namespace. The patch replaces the original symbol, not the already-imported reference.

generic

解决方案

  1. 94% 成功率
    # app/service.py: from app.mail import send_email
    def notify(user):
        send_email(user.email)
    
    # test_service.py
    from unittest.mock import patch
    @patch('app.service.send_email')
    def test_notify(mock_send):
        notify(user)
        mock_send.assert_called_once()
  2. 92% 成功率
    def test_notify(mocker):
        m = mocker.patch('app.service.send_email')
        notify(user)
        m.assert_called_once_with('[email protected]')

无效尝试

常见但无效的做法:

  1. 80% 失败

    The real function is being called, not the mock. Changing call counts doesn't make the patch take effect.

  2. 70% 失败

    autospec validates the signature but still patches the wrong namespace; the code under test still holds the original reference.