According to unittest doc (https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.configure_mock) and verified personally,
mock = Mock(some_attribute='eggs', **{'method.return_value': 3, 'other.side_effect': KeyError})
works.
Also verified
mock = Mock(some_attribute='eggs', method.return_value=3, other.side_effect=KeyError)
will raise SyntaxError: keyword can't be an expression
Should these 2 be equivalent at syntax level? What happened in the dict unpacking? If 2 doesn't work, how is 1 being handled? Is there a way to achieve the Mock init without using "**"?
Tested snippet 1: works; Tested snippet 2: raise error; Asked ChatGPT-3.5: It tells nothing valuable but keeps contradicting itself and apologizing to me. Maybe I should upgrade to 4.
This is a syntactic problem. When you unpack a dict, the only syntactic requirement for the keys is that they shall be valid strings. No more no less.
And 'method.return_value'
is a valid string.
But when you pass keyword parameters, the syntactic requirement is that they shall be valid identifiers. And as it contain a dot, method.return_value
is not a valid identifier.
You are just realizing that the unpacking kwargs
idiom is more powerful than simply passing arbitrary but declared parameters. With the **dict
idiom, the Python interpretor uses a short-circuit under the hood and directly uses the passed dictionary to build the kwargs
parameter whitout any requirement for the keys to be valid identifiers. Unsure whether it was really intended at language definition time, but it is now definitely part of the language and has real use cases like your example.