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
unittest.mock does not wrap dunder methods (__getitem__ etc) #69783
Comments
Both unittest.mock and the backported release for earlier pythons don't appear to support mocking of dictionary objects. Specifically I'm expecting that any of the methods used to test for membership, or get items from a mock object wrapping a dictionary should succeed. However it appears that MagicMock doesn't appear to support this. Attached file shows an attempt to use different methods with a wrapped dictionary object where only the '.get()' method appears to work as expected. |
Looking at the source, it's not clear that wraps is supported for __ methods, despite what the documentation implies. That is, MagicProxy doesn't seem to look at the wraps information. I suspect it is doable, but it may be an enhancement request rather than a bug fix, I'm not sure. |
I think this is a valid mock bug; it likely needs some thoughtful exhaustive testing, and obviously support added for it. |
The assertions in the attached test still fail on master (3.8a3), so this still applies. Michael, are you able to look at this, the code hasn't changed since the original PEP-417 implementation, which doesn't specify if this behaviour should be supported. The documentation does not specify that this is supported also, so i suspect this is an enhancement request.
result = self._get_child_mock(
parent=self, name=name, wraps=wraps, _new_name=name,
_new_parent=self
) |
This seems to a reasonable change to me since dict.get returns the value then making a contains check dict.__contains__ should return True instead of the fixed return value of False. Below is a patch where the mock_wraps attribute is set with the relevant method that would make sure in the report dict.get would used. diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py def _set_return_value(mock, method, name):
+ # If _mock_wraps is present then attach it so that it's return
+ # value is used when called.
+ if mock._mock_wraps is not None:
+ method._mock_wraps = getattr(mock._mock_wraps, name)
+ return
+
fixed = _return_values.get(name, DEFAULT)
if fixed is not DEFAULT:
method.return_value = fixed |
Michael, any thoughts on this? This more feels like an enhancement to me and I have marked it as 3.9 since I am not sure someone might be depending on the behavior where they have used wraps but still expect default values for magicmethods as they do now. |
As discussed with Karthik, I think this is a nice feature enhancement for the wraps functionality and worth fixing. It has the great advantage that the fix is nice and isolated and simple. |
The previous behaviour was unspecified and clearly due to missing functionality, so the advantages of fixing it outweigh any potential compatibility issues. But I'd see it as a feature enhancement for 3.9. |
The change has been reverted as per bpo-39966. I am reopening this for further discussion. |
I went through dunder methods to check if any other operators or builtins work on objects without respective dunder methods:
So in addition to __bool__, these dunder methods would have to be special cased. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: