python / python/cpython

Explain how to properly mock user-defined `__call__`

Đang mở
#131,383 9 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

docs
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu với trình tái hiện MagicMock được cung cấp trên Python 3.12 hoặc 3.13, sau đó kiểm tra unittest/mock.py quanh NonCallableMock.assert_called_with và phần xử lý chữ ký liên quan đến spec=A. So sánh hành vi của một lớp định nghĩa call với traceback hiện tại. Công việc được xem là hoàn tất khi hành vi được ghi lại trong tài liệu hoặc được triển khai khiến assertion được hiển thị thành công.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
python
Lĩnh vực
testing-qa
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
42/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.