Search code examples
pythonmockingpython-mock

Mock a method call from an object created inside a function (python)


class Foo:
       def do_work:
          client = Client()
          client.widgets(self.widget_id).parts().get()``

I have the above code. Client() class is defined in another package. I am trying to unit test it with mock as follows:

    magic_mock = MagicMock()
    api_client = Client()
    magic_mock.api_client.widgets().parts().get.return_value = self.generate_mock

Unfortunately, it doesn't seem to work. What is a better approach?


Solution

  • If your class is in mymodule.py:

    # mymodule.py
    from othermodule import Client
    
    class Foo:
        def do_work():
            client = Client()
            return client.widgets(self.widget_id).parts().get()
    

    Then your test module should be something like (implement that generate_mock instead of mocked_value):

    # test_mymodule.py
    from unittest.mock import patch
    
    import mymodule
    
    
    @patch('mymodule.Client')
    def test_client_widgets_parts_get_returned(mocked):
        mocked_value = "foo"
        mocked.return_value.widgets.return_value.parts.return_value.get.return_value = mocked_value
        returned = mymodule.Foo().do_work()
        assert returned == mocked_value
    

    Or without changing your do_work:

    @patch('mymodule.Client')
    def test_client_widgets_parts_get_called(mocked):
        mymodule.Foo().do_work()
        mocked.return_value.widgets.return_value.parts.return_value.get.assert_called()
    

    P.S. stacked decorators are added from the bottom:

    @patch('mymodule.Other')
    @patch('mymodule.Client')
    def test_client_widgets_parts_get_called(mocked_client, mocked_other):