Explain how to properly mock user-defined `__call__`
未关闭
还没有人认领这个 Issue。
docs
- 主要语言
- Python
- 星标
- 77.2k
- 派生
- 36k
- PR 合并指标
- PR 指标待抓取
描述
Bug report
Bug description:
Reproduce
from unittest.mock import MagicMock
class A:
def __init__(self, a):
...
def __call__(self, b, c):
...
mocker = MagicMock(spec=A)
mocker(21, 42)
mocker.assert_called_once_with(21, 42)
Current Behavior
TypeError Traceback (most recent call last)
TypeError: too many positional arguments
The above exception was the direct cause of the following exception:
AssertionError Traceback (most recent call last)
Cell In[6], line 10
8 mocker = MagicMock(spec=A)
9 mocker(21, 42)
---> 10 mocker.assert_called_once_with(21, 42)
File ~/.pyenv/versions/3.12.2/lib/python3.12/unittest/mock.py:956, in NonCallableMock.assert_called_once_with(self, *args, **kwargs)
951 msg = ("Expected '%s' to be called once. Called %s times.%s"
952 % (self._mock_name or 'mock',
953 self.call_count,
954 self._calls_repr()))
955 raise AssertionError(msg)
--> 956 return self.assert_called_with(*args, **kwargs)
File ~/.pyenv/versions/3.12.2/lib/python3.12/unittest/mock.py:944, in NonCallableMock.assert_called_with(self, *args, **kwargs)
942 if actual != expected:
943 cause = expected if isinstance(expected, Exception) else None
--> 944 raise AssertionError(_error_message()) from cause
AssertionError: expected call not found.
Expected: mock(21, 42)
Actual: mock(21, 42)
Expected behaviour
It succeeds
Investigation
When passing a class that implements the __call__ method as spec to a mock instance it takes the it takes the signature of the __init__ which if it is the intended behavior is quite confusing.
CPython versions tested on:
3.12, 3.13
Operating systems tested on:
macOS, Linux
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
先在 Python 3.12 或 3.13 上使用提供的 MagicMock 复现代码,然后检查 unittest/mock.py 中 NonCallableMock.assert_called_with 附近的代码,以及与 spec=A 相关的签名处理。将定义了 call 的类的行为与当前的 traceback 进行比较。当文档化的或已实现的行为使所示 assertion 成功时,即视为完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- python
- 领域
- testing-qa
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 42/100