user3064538
user3064538

Reputation:

How do I mock the default arguments of a function that is used by the function I'm testing?

I have this my_module.py:

def _sub_function(do_the_thing=True):
    if do_the_thing:
        do_stuff()
    else:
        do_something_else()


def main_function():
    # do some stuff
    if some_condition:
        return _sub_function()
    else:
        return _sub_function(do_the_thing=False)

then I have this test, test_my_module.py:

import unittest
from unittest import mock

import my_module


class TestMyModule(unittest.TestCase):
    @mock.patch.object("my_module._sub_function", "__defaults__", (False,))
    def test_main_function(self):
        print(my_module.main_function())


if __name__ == "__main__":
    unittest.main()

I have a function _sub_function that takes a default argument that decides if it performs some steps or not. Normally, main_function calculates when those actions need to be performed and overrides that default argument. Unfortunately, when running tests I can't perform those actions when I normally need to.

So my idea was to use a default argument on _sub_function and in my test to patch the function to monkey-patch that argument to be False so that it skips these actions during testing. Unfortunately I can't use the code in this question because I'm testing main_function, and not _sub_function, so I don't have _sub_function in my test. mock.patch.object can only take the object being patched as an argument, not a string containing the import path of the object (like mock.patch does), so the above code doesn't work, it raises an AttributeError: my_module._sub_function does not have the attribute '__defaults__' on the mock.patch.object() line.

Is there a way to patch a functions default arguments using the string import path of that function.

Or is there a better way to achieve what I want?

Upvotes: 5

Views: 2032

Answers (1)

chepner
chepner

Reputation: 530970

The only problem is you are trying to patch an attribute of a str object, not your function:

class TestMyModule(unittest.TestCase):
    @mock.patch.object(my_module._sub_function, "__defaults__", (False,))
    def test_main_function(self):
        print(my_module.main_function())

The AttributeError being raised doesn't make that clear, unfortunately.

Upvotes: 3

Related Questions