This question is a follow-up to this brilliant answer on decorators in Python :
I use the given “snippet to make any decorator accept generically any argument”.
Then I have this (here simplified) decorator:
@decorator_with_args
def has_permission_from_kwarg(func, *args, **kwargs):
"""Decorator to check simple access/view rights by the kwarg."""
def wrapper(*args_1, **kwargs_1):
if 'kwarg' in kwargs_1:
kwarg = kwargs_1['kwarg']
else:
raise HTTP403Error()
return func(*args_1, **kwargs_1)
return wrapper
- Working with this decorator, no problem it does the job very well.
- Testing a similar decorator that does not require absolutely the kwargs, same outcome.
-
But testing this decorator with the following mock does not work:
def test_can_access_kwarg(self): """Test simple permission decorator.""" func = Mock(return_value='OK') decorated_func = has_permission_from_slug()(func(kwarg=self.kwarg)) # It will raise at the following line, whereas the kwarg is provided... response = decorated_func() self.assertTrue(func.called) self.assertEqual(response, 'OK')
It returns me the exception I am raising when I do not have a ‘kwarg’ keyword-argument…
Does anyone has a clue how to test (by mocking would be preferable) such a decorator decorated by another decorator that requires the access to one of the keyword arguments passed to the function ?
This will:
func(kwarg=self.kwarg)Return the wrapper which will then later try to call the results from step 3 (which would fail).
response = decorated_func()
This will then call the returned wrapper with no arguments, so
**kwargs_1is empty. Also, if you wrapper wouldn’t raise an exception in this case, the subsequent call offunc(..)would throw an exception because the return value offunc(the original one) is probably not callable (see above).What you probably want to do instead, or at least what your decorator supports, is this:
Or, if you want to pass your
kwargin the decorator like this:Then you need to adjust or decorator to actually use
kwargs, and notkwargs_1in the check (the latter are the arguments to the decorated function).I’m testing your original decorator definition (with no changes) and the
decorator_with_argsas defined in the linked answer with the following code:As expected, I get
func (); {'kwarg': 'foo'}printed for the first call, and a HTTP403 exception for the second.