aboutsummaryrefslogtreecommitdiffstats
path: root/tests/helpers.py
diff options
context:
space:
mode:
authorGravatar MarkKoz <[email protected]>2020-05-10 17:47:09 -0700
committerGravatar MarkKoz <[email protected]>2020-05-11 12:03:11 -0700
commit34b836a8eba0f006c77a7b3f48f7ab14c37d31ee (patch)
tree8b34a7862c490e6fe5b2ac694bd29db353919c0a /tests/helpers.py
parentTest token regex doesn't match invalid tokens (diff)
Fix autospec decorator when used with multiple attributes
The original approach of messing with the `attribute_name` didn't work for reasons I won't discuss here (would require knowledge of patcher internals). The new approach doesn't use patch.multiple but mimics it by applying multiple patch decorators to the function. As a consequence, this can no longer be used as a context manager.
Diffstat (limited to 'tests/helpers.py')
-rw-r--r--tests/helpers.py28
1 files changed, 12 insertions, 16 deletions
diff --git a/tests/helpers.py b/tests/helpers.py
index 1ab8b455f..dfbe539ec 100644
--- a/tests/helpers.py
+++ b/tests/helpers.py
@@ -24,25 +24,21 @@ for logger in logging.Logger.manager.loggerDict.values():
def autospec(target, *attributes: str, **kwargs) -> unittest.mock._patch:
- """
- Patch multiple `attributes` of a `target` with autospecced mocks and `spec_set` as True.
-
- To allow for arbitrary parameter names to be used by the decorated function, the patchers have
- no attribute names associated with them. As a consequence, it will not be possible to retrieve
- mocks by their attribute names when using this as a context manager,
- """
+ """Patch multiple `attributes` of a `target` with autospecced mocks and `spec_set` as True."""
# Caller's kwargs should take priority and overwrite the defaults.
kwargs = {'spec_set': True, 'autospec': True, **kwargs}
- attributes = {attribute: unittest.mock.DEFAULT for attribute in attributes}
-
- patcher = unittest.mock.patch.multiple(target, **attributes, **kwargs)
-
- # Unset attribute names to allow arbitrary parameter names for the decorator function.
- patcher.attribute_name = None
- for additional_patcher in patcher.additional_patchers:
- additional_patcher.attribute_name = None
- return patcher
+ # Import the target if it's a string.
+ # This is to support both object and string targets like patch.multiple.
+ if type(target) is str:
+ target = unittest.mock._importer(target)
+
+ def decorator(func):
+ for attribute in attributes:
+ patcher = unittest.mock.patch.object(target, attribute, **kwargs)
+ func = patcher(func)
+ return func
+ return decorator
class HashableMixin(discord.mixins.EqualityComparable):