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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With