saurbh
saurbh

Reputation: 511

Mock a function passed as default parameter

I have a python file (a.py) which defines a function, and a class which uses it as a default parameter in it's init method and initializes another imported class. This is my a.py

import OtherClass

def useful_default_func():
    //do something useful

class MyClass(object):
    def __init__(self, def_func=useful_default_func):
        self.other_class = OtherClass(def_func())
        //do something useful

I am trying to mock the useful_default_func in my test file.

class TestMyClass(unittest.TestCase):
    @patch('a.useful_default_func')
    @patch('a.OtherClass')
    test_init(self, mock_other_class, mock_default_func):
        myc= MyClass()
        mock_other_class.assert_called_once_with(mock_default_func)
        // further tests

However, the mock_default_func is not patching and my test fails saying,

Expected: OtherClass(<MagicMock id='xxx'>)
Actual: OtherClass(<function useful_default_func at 0x7f155858b378>)

Fairly new to the python mock lib, so not really sure, what is happening here or what I am doing wrong or how should I be approaching it?

Upvotes: 1

Views: 256

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16805

Something like this could work:

def mocked_fct():
    return 42

class TestMyClass(unittest.TestCase):
    @mock.patch.object(a.MyClass.__init__, '__defaults__', (mocked_fct,))
    @patch('a.OtherClass')
    def test_init(self, mock_other_class):
        myc = MyClass()
        mock_other_class.assert_called_once_with(mocked_fct)

I didn't use a mock for the mocked default function here, this can be changed if needed. The main point is that you can mock the function defaults.

Note: this assumes that you call

self.other_class = OtherClass(def_func)

instead of

self.other_class = OtherClass(def_func())

If this was not a typo, your assertion would not be correct. In this case, you could instead use:

mock_other_class.assert_called_once_with(mocked_fct())
mock_other_class.assert_called_once_with(42)  # same as above

Upvotes: 1

Related Questions