Skip to content

Fix unittest.mock.patch and unittest.mock.patch.object when new_callable is not None #14358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

leonarduschen
Copy link

@leonarduschen leonarduschen commented Jul 1, 2025

This PR fixes multiple issues with unittest.mock.patch and unittest.mock.patch.object

  • Both should only accept Callable | None for new_callable, currently Any | None
  • When used as context managers, both should return T for new_callable: Callable[..., T], currently they both return Mock | AsyncMock
  • When used as decorators to functions:
    • When neither new nor new_callable is given, the function signature should be updated (the mock is passed as last parameter), patch already has the correct behavior but patch.object does not
    • When new_callable is given, same as above, should update function signature. patch already has the correct behavior (by chance, explicit new_callable is not actually handled), but patch.object does not

Addresses #14339

@leonarduschen leonarduschen changed the title Fix patch and patch.object when new_callable is not None Fix unittest.mock.patch and unittest.mock.patch.object when new_callable is not None Jul 1, 2025

This comment has been minimized.

Copy link
Collaborator

@hauntsaninja hauntsaninja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be interested in adding a few test cases to https://github.com/python/typeshed/blob/main/stdlib/%40tests/test_cases/check_unittest.py ? (the unittest.mock stubs can get a little tricky)

@leonarduschen
Copy link
Author

sure!

Copy link
Contributor

github-actions bot commented Jul 2, 2025

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

@leonarduschen
Copy link
Author

I've updated the original PR description to explain what this PR is fixing

@@ -5,9 +5,9 @@
from datetime import datetime, timedelta
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test result with old implementation

check_unittest.py:190: error: Expression is of type "MagicMock | AsyncMock", not "int"  [assert-type]
check_unittest.py:213: error: Missing positional argument "mock" in call to "obj_f_default_new"  [call-arg]
check_unittest.py:214: error: Missing positional argument "mock" in call to "obj_f_default_new"  [call-arg]
check_unittest.py:214: error: Argument 1 to "obj_f_default_new" has incompatible type "str"; expected "int"  [arg-type]
check_unittest.py:217: error: Missing positional argument "new_callable_ret" in call to "obj_f_explicit_new_callable"  [call-arg]
check_unittest.py:218: error: Missing positional argument "new_callable_ret" in call to "obj_f_explicit_new_callable"  [call-arg]
check_unittest.py:218: error: Argument 1 to "obj_f_explicit_new_callable" has incompatible type "str"; expected "int"  [arg-type]
check_unittest.py:228: error: Expression is of type "MagicMock | AsyncMock", not "int"  [assert-type]

This agrees with the upated PR description:

This PR fixes multiple issues with unittest.mock.patch and unittest.mock.patch.object

  • Both should only accept Callable | None for new_callable, currently Any | None

  • When used as context managers, both should return T for new_callable: Callable[..., T], currently they both return Mock | AsyncMock

  • When used as decorators to functions:

    • When neither new nor new_callable is given, the function signature should be updated (the mock is passed as last parameter), patch already has the correct behavior but patch.object does not
    • When new_callable is given, same as above, should update function signature. patch already has the correct behavior (by chance, explicit new_callable is not actually handled), but patch.object does not

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants