Unittest.mock.patch: Context manager vs setUp / tearDown in unittest

There seem to be 2 ways to use unittest.mock.patch , is one better way?

Using the context manager and operator:

class MyTest(TestCase):
    def test_something(self):
        with patch('package.module.Class'):
            assert package.module.Class is self.MockClass

      

Or call start and stop from install and tearDown / cleanup:

class MyTest(TestCase):
    def setUp(self):
        patcher = patch('package.module.Class')
        self.MockClass = patcher.start()
        self.addCleanup(patcher.stop)

    def test_something(self):
        assert package.module.Class is self.MockClass

      

The context manager version is less code and therefore easier to read. I have some reason why I should prefer using the setUp / tearDown TestCase framework?

+3


source to share


2 answers


The main reason for speculating that the fix setUp

would be if you had more than one test that required that class to be fixed. In this case, you will need to duplicate the statement with

in each test.



If you only have one test that requires a patch, I would prefer the with statement to be readable.

+2


source


There is also a third way to use it as a decorator:

class MyTest(testcase):

    @unittest.mock.patch('package.module.Class')
    def test_something(self):
        assert package.module.Class is self.MockClass

      

This is even less code, but it might not be relevant.



There are a couple of considerations: (1) (as babbageclunk pointed out) if you need to reuse a patch then a simple, boring call to build one in setUp

, is the best and most readable. (2) if you want to create some kind of metaprogramming facility so that you can enable or disable patching when running tests, then the decorator approach will save you a ton of trouble. In this case, you can write an additional decorator or use a global variable (ick) to control whether patch decorators are applied to test functions or not. If they are embedded in function definitions, then you have to manually deal with them if you ever want to disable fixing when running tests. One simple reason you might want to do this is to just run your tests without patches to cause a lot of crashes and watch which parts you haven't implemented yet (your decorator for metaprogramming patches is essentiallycould catch these problems and print a goodNotImplemented

exceptions for you, or even create a report containing such things). There could be many more reasons requiring precise control over whether (and to what extent) a fix will be "posted" in the test suite at any given time.

The decorator approach is also good in that (a) it allows you to isolate which patches go to which test functions are outside of that function, but without passing it setUp

, and (b) it makes it very clear to the reader when a given function requires a specific patch.

In this case, the context manager version does not have many advantages, as it is hardly readable than the decorator version. But, if there really is only one case, or a very small set of specific cases where this is used, then the context manager version will be fine.

+2


source







All Articles