获取Pytest,相对导入和Patch.Object进行协作

时间:2019-12-31 01:19:12

标签: python mocking pytest

我很难受pytest,相对导入和补丁的配合。

我有以下内容:

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):
        ...

我尝试了一些变化。

  1. 当前显示的一个。 Pytest返回“ TypeError:test_cleanup()恰好接受4个参数(给定2个)”。即使我确定我根据https://docs.python.org/3/library/unittest.mock-examples.html
  2. 正确使用了它们,也无法识别patch.objects
  3. 将patch.objects更改为简单补丁会导致它们抛出“没有名为cleanup的模块”。我不知道如何在相对导入中使用补丁。

1 个答案:

答案 0 :(得分:1)

这实际上与pytest没有任何关系,而仅仅是mock装饰器的行为

来自the docs

如果将patch()用作修饰符,而省略了new,则将创建的模拟作为附加参数传递给修饰的函数

也就是说,因为您要传递替换对象,所以不会发生签名突变

例如:

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'

幸运的是,如果要生成mock对象,则几乎不需要实际传递new参数,并且可以使用关键字选项

对于您的特定示例,这应该可以正常工作:

    @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): ...

如果您绝对需要将它们设为MagicMock,则可以使用new_callable=MagicMock关键字参数