5
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?

laconicdev
  • 6,360
  • 11
  • 63
  • 89

1 Answers1

8

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):
ipaleka
  • 3,745
  • 2
  • 13
  • 33
  • Thank you. This works. However, it turns out, I have another external object inside mymodule.Foo().do_work() that needs patched. What is the proper syntax for that? – laconicdev Aug 08 '19 at 18:45