【问题标题】:Getting Pytest, Relative Import, and Patch.Object to Cooperate让 Pytest、Relative Import 和 Patch.Object 协同工作
【发布时间】:2019-12-31 01:19:12
【问题描述】:

我在获取 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 个)”。它无法识别patch.objects,即使我很确定我根据https://docs.python.org/3/library/unittest.mock-examples.html正确使用它们
  2. 将 patch.objects 更改为简单的补丁会导致它们抛出“没有名为 cleanup 的模块”。我不知道如何将补丁与相对导入一起使用。

编辑:我正在使用 Python 2.7,以防万一。

【问题讨论】:

  • 这看起来是正确的 - 也许您使用的是旧版本的 pytest 无法识别模拟?
  • 我检查了这个。 pytest 确实可以识别我正在使用的其他模拟。
  • 哦,我仔细阅读后明白了,它与 pytest 无关——让我写一个答案

标签: python mocking pytest


【解决方案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): ...

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

【讨论】:

    猜你喜欢
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2011-09-25
    • 2016-03-09
    • 1970-01-01
    相关资源
    最近更新 更多