{
  "id": "python/mock-patch-wrong-target",
  "signature": "AssertionError: Expected 'send_email' to be called once. Called 0 times.",
  "signature_zh": "AssertionError: 期望 'send_email' 被调用一次。实际调用 0 次。",
  "regex": "AssertionError:\\ Expected\\ 'send_email'\\ to\\ be\\ called\\ once\\.\\ Called\\ 0\\ times\\.",
  "domain": "python",
  "category": "runtime_error",
  "subcategory": null,
  "root_cause": "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.",
  "root_cause_type": "generic",
  "root_cause_zh": "unittest.mock.patch 打补丁的对象是函数定义所在的模块，但被测代码通过 from ... import 把该函数导入了自己的命名空间。补丁替换的是原始符号，而非已导入的引用。",
  "versions": [
    {
      "version": "3.11",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    },
    {
      "version": "3.12",
      "introduced": null,
      "deprecated": null,
      "removed": null,
      "behavior_change": null,
      "status": "active"
    }
  ],
  "os_specific": {},
  "dead_ends": [
    {
      "action": "",
      "why_fails": "The real function is being called, not the mock. Changing call counts doesn't make the patch take effect.",
      "fail_rate": 0.8,
      "condition": "",
      "sources": []
    },
    {
      "action": "",
      "why_fails": "autospec validates the signature but still patches the wrong namespace; the code under test still holds the original reference.",
      "fail_rate": 0.7,
      "condition": "",
      "sources": []
    }
  ],
  "workarounds": [
    {
      "action": "",
      "success_rate": 0.94,
      "how": "# app/service.py: from app.mail import send_email\ndef notify(user):\n    send_email(user.email)\n\n# test_service.py\nfrom unittest.mock import patch\n@patch('app.service.send_email')\ndef test_notify(mock_send):\n    notify(user)\n    mock_send.assert_called_once()",
      "condition": "",
      "sources": []
    },
    {
      "action": "",
      "success_rate": 0.92,
      "how": "def test_notify(mocker):\n    m = mocker.patch('app.service.send_email')\n    notify(user)\n    m.assert_called_once_with('a@b.com')",
      "condition": "",
      "sources": []
    }
  ],
  "workarounds_zh": [],
  "transition_graph": {
    "leads_to": [],
    "preceded_by": [],
    "frequently_confused_with": []
  },
  "official_doc_url": null,
  "official_doc_section": null,
  "error_code": null,
  "verification_tier": "ai_generated",
  "confidence": 0.89,
  "fix_success_rate": 0.8,
  "resolvable": "true",
  "first_seen": "2024-01-19",
  "last_confirmed": "2025-01-01",
  "last_updated": "2025-01-01",
  "evidence_count": 0,
  "tags": [],
  "locale": "en",
  "aliases": []
}