Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setUp function for python unittest doesn't use mocks declared over the class

so I'm writing unit tests and I'm having trouble with the setUp function. From what I've seen, it's supposed to just execute code before your function and thus I could put anything that's repetitive in there. However, this function doesn't seem to be applying the mocks I've created as patch decorators over the entire class. This is a small piece of what I want it to look like:

@patch('geomet_data_registry.layer.base.get_today_and_now', new=mocked_get_date)  # noqa
@patch('geomet_data_registry.layer.base.load_plugin', new=mocked_load_plugin)
@patch('geomet_data_registry.layer.base.TILEINDEX_PROVIDER_DEF', new=mocked_tileindex)  # noqa
@patch('geomet_data_registry.layer.base.STORE_PROVIDER_DEF', new=mocked_store)
class TestInitBase(unittest.TestCase):

    def setUp(self):
        """ Code that executes before every function. """

        self.maxDiff = None
        self.today_date = \
            datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
        mocked_get_date.return_value = self.today_date
        self.base_layer = BaseLayer({'name': 'model_gem_global'})

    def test_Init(self):
        
        expected_values = {'items': [],...

        base_layer_attr = self.base_layer.__dict__

        self.assertDictEqual(expected_values, base_layer_attr, msg=None)

Here I mock the date received so it doesn't mess with my tests, I mock load_plugin, which when used returns a class instance of a certain plugin, I mock TileIndex which is an ES TileIndex and I mock the store, which is a redis store. If I use the code shown above, it doesn't work. When I instantiate the class BaseLayer inside setUp, none of my mocks are used and I get:

-  'receive_datetime': '2021-11-10T12:56:07.371067Z',
?                                              ^^^
+  'receive_datetime': '2021-11-10T12:56:07.371131Z',
?                                              ^^^
-  'store': <MagicMock name='mock()' id='140158154534472'>,
-  'tileindex': <MagicMock name='mock()' id='140158154534472'>,
+  'store': <BaseStore> Redis,
+  'tileindex': <ElasticsearchTileIndex> http://localhost:9200,

However, before you tell me maybe my paths are wrong for the mocks or something like that, I can assure you that everything works fine, because the code works if I keep everything the same, except I repeat the class instantiation in every test function. Moreover, it will work if I keep this the same, but I name the setUp for example mySetUp and call it at the beginning of the function.

Everything works this way and I've already made all my tests without using the setUp at all because I remember thinking to myself "this thing is broken I'm not risking using this function in my tests".

Thanks!

like image 423
PhilippeTh Avatar asked Sep 05 '25 03:09

PhilippeTh


1 Answers

By default the mock.patch decorator is applied to each function in the class starting with test. Since setUp does not start with test it will not be patched by the class decorator by default.

You can change this by setting patch.TEST_PREFIX (https://docs.python.org/3/library/unittest.mock.html#test-prefix). If you want it to apply to setUp as well you can do

patch.TEST_PREFIX = ("test", "setUp",)

and use the class decorators as before.

like image 195
Nick Addison Avatar answered Sep 07 '25 20:09

Nick Addison