问题
I have a decorator @auth
which basically checks a database to ensure a user can access a given REST call. I would like to write some unit tests for these calls. My initial idea was to simply monkeypatch the decorator into a pass through that does nothing. (My initial idea failed, so I may just monkeypatch some function inside of @auth
so that it always passes, but I'm still curious if I can bypass a decorator completely)
I threw together a quick sample of what I was hoping to accomplish.
example.py
# example.py
from __future__ import print_function
def sample_decorator(func):
def decorated(*args, **kwargs):
print("Start Calculation")
ans = func(*args, **kwargs) + 3
print(ans)
print("Finished")
return ans
return decorated
@sample_decorator
def add(a, b):
return a + b
test_example.py
# test_example.py
from __future__ import print_function
import pytest
import example
def test_add_with_decorator():
assert example.add(1, 1) == 5
def testadd_with_monkeypatch_out_decorator(monkeypatch):
monkeypatch.setattr(example, 'sample_decorator', lambda func: func)
assert example.add(1, 1) == 2 # this fails, but is the behaviour I want
Is there some straight forward way to accomplish this?
回答1:
The decorator can set an attribute on the wrapping function to give access to the wrapped function.
Something along the line of
def wrap_foo(func):
def decorated(*args, **kwargs):
func(*args, **kwargs)
decorated.__wrapped__ = func
return decorated
@wrap_foo
def foo():
pass
# Wrapped
foo()
# Unwrapped
foo.__wrapped__()
回答2:
Just keep the definitions separate:
def raw_add...
add = sample_decorator(raw_add)
assert example.raw_add...
来源:https://stackoverflow.com/questions/41206565/bypassing-a-decorator-for-unit-testing