Getting Pytest, Relative Import, and Patch.Object to Cooperate

荒凉一梦 提交于 2021-01-29 16:29:48

问题


I'm having a hell of a time getting pytest, relative import, and patch to cooperate.

I have the following:

from .. import cleanup

class CleanupTest(unittest.TestCase):

    @patch.object(cleanup, 'get_s3_url_components', MagicMock())
    @patch.object(cleanup, 'get_db_session', MagicMock(return_value={'bucket', 'key'}))
    @patch('time.time')
    def test_cleanup(self, mock_time, mock_session, mock_components):
        ...

I've tried a few variations.

  1. The currently shown one. Pytest returns 'TypeError: test_cleanup() takes exactly 4 arguments (2 given)'. It's not recognizing the patch.objects, even though I'm pretty sure I'm using them correctly according to https://docs.python.org/3/library/unittest.mock-examples.html
  2. Changing the patch.objects over to simple patches causes them to throw 'no module named cleanup'. I can't figure out how to use patch with a relative import.

Edit: I'm using Python 2.7 in case that's relevant.


回答1:


this actually doesn't have anything to do with pytest and is merely the behaviour of the mock decorators

From the docs

If patch() is used as a decorator and new is omitted, the created mock is passed in as an extra argument to the decorated function

that is, because you're passing a replacement object the signature-mutation doesn't occur

For example:

from unittest import mock

class x:
    def y(self):
        return 'q'

@mock.patch.object(x, 'y', mock.Mock(return_value='z'))
def t(x): ...


t()  # TypeError: t() missing 1 required positional argument: 'x'

Fortunately, if you're producing a mock object, you rarely need to actually pass in the new argument and can use the keyword options

For your particular example this should work fine:

    @patch.object(cleanup, 'get_s3_url_components')
    @patch.object(cleanup, 'get_db_session', return_value={'bucket', 'key'})
    @patch('time.time')
    def test_cleanup(self, mock_time, mock_session, mock_components): ...

If you absolutely need them to be MagicMocks, you can use the new_callable=MagicMock keyword argument



来源:https://stackoverflow.com/questions/59538556/getting-pytest-relative-import-and-patch-object-to-cooperate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!