pytest - 在构造函数中模拟构造函数

pytest - Mocking constructor within constructor

全部,

我有一个class类似的。

from mod import Bar

class Foo:
  def __init__(self):
    self.obj = Bar()

如何使用 pytest / pytest-mock 模拟 Bar 构造函数?我尝试了以下未成功。

def test():
  with mock.patch('mod.Bar') as patched:
    Foo()

您必须修补名称,而不是实例。

来自官方Python文档:Where to patch

patch() works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test.

在您的示例中,您的 class Foo 是在模块 foomod.py 中定义的,因此您必须修补 foomod.Bar 而不是 mod.Bar

您可以使用 pytest-mock 中的 mocker 夹具或 unittest.mock.patch.

将其放入夹具中
@pytest.fixture # With pytest-mock
def mock_bar(mocker):
    return mocker.patch('foomod.Bar')

@pytest.fixture # With stdlib
def mock_bar():
    with patch('foomod.Bar') as mock:
        yield mock

# Usage
def test_foo(mock_bar):
    pass

据我所知,这两种方法之间没有显着差异。当夹具超出范围时,两者都会被清理。

我使用以下方法模拟对象 pytest 而没有 fixture 装饰器

# path.to.MyClass
class MyClass():
    def __init__(self, some_parameter: SomeObject) -> None:
        self.some_value = some_parameter

    def get_something(self) -> str:
        return 'Hello'


# tests.py
from pytest_mock.plugin import MockerFixture
from unittest.mock import MagicMock

def test_with_mock(mocker: MockerFixture) -> None:
    mock_myclass: MagicMock = mocker.patch('path.to.MyClass')

    mock_myclass_get_something: MagicMock = mocker.patch('path.to.MyClass.get_something')
    mock_myclass_get_something.return_value = 'World!'

    assert mock_myclass.get_something() == 'World!'