NonePytest - конструктор-пересмешник внутри конструктора

Все,

У меня есть класс, похожий на этот.

from mod import Bar

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

Как мне издеваться Bar конструктор, использующий pytest / pytest-mock? Я попытался следующее безуспешно.

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

2 ответа

Решение

Вы должны исправить имя, а не экземпляр.

Из официальной документации Python: где патчить

patch() работает (временно) изменяя объект, на который указывает имя, с другим. Может быть много имен, указывающих на какой-либо отдельный объект, поэтому для исправления необходимо убедиться, что вы исправили имя, используемое тестируемой системой.

В вашем примере ваш класс Foo определяется в модуле foomod.pyтак что надо исправлять foomod.Bar вместо mod.Bar,

Вы можете поместить это в прибор, используя mocker крепление от pytest-mock или с 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!'
Другие вопросы по тегам