Предположим, у меня есть декоратор, который собирает все функции, которые он украшает, для вызова в будущем.
mydecorator.py
class CallLater(object):
funcs = []
def __init__(self, func):
self.funcs.append(func)
@classmethod
def call_now(cls, *args, **kwargs):
for func in cls.funcs:
func(*args, **kwargs)
Тогда , У меня есть функция в модуле, одна из которых будет сохранена моим декоратором.
mymodule.py
import logging
from mydecorator import CallLater
logging.basicConfig(level=logging.INFO)
@CallLater
def log_a():
logging.info("A")
@CallLater
def log_b():
logging.info("B")
def log_c():
logging.info("C")
Теперь, если я импортирую mymodule
и позвоните CallLater.call_now()
, log_a
и log_b
. Но скажем, что во время тестирования я хочу заменить log_b
на log_c
. Я постараюсь сделать замену с помощью макета.
mock_test.py
import logging
import pytest
from mymodule import log_a, log_c
from mydecorator import CallLater
logging.basicConfig(level=logging.INFO)
pytest_plugins = ('pytest_mock',)
def test_mocking(mocker, caplog):
mocker.patch('mymodule.log_b', log_c)
CallLater.call_now()
logs = [rec.message for rec in caplog.records]
assert logs == ["A", "C"]
Но когда я запускаю pytest
, я вижу, что мой макет не не работает.
FAILED mock_test.py::test_mocking - AssertionError: assert ['A', 'B'] == ['A', 'C']
Я думаю, что 'mymodule.log_b'
- неправильная цель для насмешки, так как она не вызывается как mymodule.log_b()
, но я не уверен, что использовать вместо этого в этой ситуации. Любой совет приветствуется!