I'm writing an internal unit tests framework which involves mocking multiple functions/classes.
@patch seems to be working great for my needs, but as there are many tests that will require to patch many different classes/functions, I'm looking to avoid writing multiple @patch before every test and maybe encapsulate them all into another decorator.
To better illustrate my needs:
current state:
@patch('p.A', mockedA)
@patch('p.B', mockedB)
.
.
@patch('p.N', mockedN)
def test_this()
desired state:
@patch_all
def test_this()
Is it possible to implement something like this?, so far I wasn't able to as @patch requires to be followed either def or another @.
EDIT 2:
I've tried Michele's suggestion, but the test is no longer being identified as a test:
After adding functools.wraps to the patch_all decorator, it worked.
def patch_all(f):
@patch('p.A', moduleA.classA.methodA)
@patch('p.B', moduleB.classB.methodB)
.
.
@patch('p.N', moduleN.classN.methodN)
wraps(f)
def functor(*args, **kwargs):
return f(*args, **kwargs)
return functor
class TestWrapper(unittest.TestCase):
@patch_all
def my_test(self):
my test goes here...
With the @patch_all decorator this is what I get:
nosetests Tester.py --nocapture
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
If I remove it:
$ nosetests Tester.py --nocapture
.
----------------------------------------------------------------------
Ran 1 test in 7.692s
OK
Thanks in advance.
patch
decorator like all decorators is just a function that take a function and return a function ([EDIT] in the original version I forgot @functools.wraps(f)
to make a correct test decorator, thanks to @MenyIssakov to let me know that my answer was wrong). You can define your own patch_all
decorator like
def patch_all(f):
@patch('p.A', argsA)
@patch('p.B', argsB)
.
.
@patch('p.N', argsN)
@functools.wraps(f)
def functor(*args, **kwargs):
return f(*args, **kwargs)
return functor
Now you can use @patch_all
decorator in your tests like:
@patch_all
def test_all(mockN, ..., mockB, mockA):
my beautiful test
You can go over this and define your own decorator that take a list of tuple to pass to the patch calls.
However i think that is not a good idea: test should be simple and mocking should be explicit to make clear the aim of the test. If you must patch a lot of objects/methods/functions in a lot of tests functions consider to apply the decorator to the class instead of the single methods to write it just one time for all test methods.