Reputation: 685
I'm trying write some unittests for my code which in turn uses a decorator
import unittest
from unittest.mock import patch
from functools import wraps
def decorator(f):
@wraps(f)
def decorated(x):
return f(x+1)
return decorated
@decorator
def get_value(x):
return x
class MyTestCase(unittest.TestCase):
@patch('file.decorator', lambda f: f)
def test_something(self):
result = get_value(1)
self.assertEqual(1, result)
I'm trying to mock the decorated function to just return f and completely bypass the decorator logic part. This is talked about in Overriding decorator during unit test in python but doesn't really work.
Upvotes: 5
Views: 4744
Reputation: 531205
Since the decorator runs immediately after you define get_value
, it's too late to mock the decorator. What you can do, though, (since you used functools.wraps
) is mock get_value
itself and use get_value.__wrapped__
(the original function) in some way. Something like
@patch('tmp.get_value', get_value.__wrapped__)
def test_something(self):
result = get_value(1)
self.assertEqual(1, result)
(In this case, I put your original code, with the above change, in tmp.py
, and ran it as python3 -munittest tmp.py
, hence my patching of the reference tmp.get_value
.)
If you anticipate the need to test the undecorated original, though, it might be simpler to keep it under its own (private) name to test: no patching needed.
import unittest
from functools import wraps
def decorator(f):
@wraps(f)
def decorated(x):
return f(x+1)
return decorated
def _get_value(x):
return x
get_value = decorator(_get_value)
class MyTestCase(unittest.TestCase):
def test_something(self):
result = _get_value(1)
self.assertEqual(1, result)
Upvotes: 5