Например, каждый раз, когда тест находит
database.db.session.using_bind("reader")
Я хочу удалить using_bind("reader"))
и просто работать с
database.db.session
используя насмешник
Пытался использовать это так в conftest.py
@pytest.fixture(scope='function')
def session(mocker):
mocker.patch('store.database.db.session.using_bind', return_value=_db.db.session)
Но пока ничего не получилось.
Тестируемый код:
from store import database
results = database.db.session.using_bind("reader").query(database.Order.id).join(database.Shop).filter(database.Shop.deleted == False).all(),
и я получаю
AttributeError: 'scoped_session' object has no attribute 'using_bind' as an error.
@Samwise from store import database results = database.db.session.using_bind("reader").query(database.Order.id).join(database.Shop).filter(database.Shop.deleted == False).all()
, и я получаю AttributeError: 'scoped_session' object has no attribute 'using_bind'
как ошибку. Вот почему я хочу удалить using_bind
Поместите это в вопрос с правильным форматированием, пожалуйста, не все в одну строку в комментарии.
@Samwise да, извини за это
Код было бы легче тестировать, если бы он находился в функции, а не на верхнем уровне модуля — как есть, он будет выполняться, как только вы импортируете модуль, что затрудняет правильную настройку макетов. .
Если бы вы могли переместить код в функцию, вы могли бы сделать что-то вроде исправления database
в тестируемом модуле, импортировать реальный store
в свой тест, а затем установить mock_database.db.session.using_bind.return_value = store.database.db.session
в своем тесте перед вызовом тестируемой функции. Таким образом, ваш макет using_bind
перенаправляется на настоящий store.database.session
.
@Samwise, так что, когда мой код находится в функции, скажем, def foo():
что я могу установить в своем тесте def test_foo(mocker):
?
Начнем с MRE, где тестируемый код использует поддельную базу данных:
from unittest.mock import Mock, patch
class Session:
def using_bind(self, bind):
raise NotImplementedError(f"Can't bind {bind}")
def query(self):
return "success!"
database = Mock()
database.db.session = Session()
def code_under_test():
return database.db.session.using_bind("reader").query()
def test():
assert code_under_test() == "success!"
Запуск этого теста завершается с ошибкой:
E NotImplementedError: Can't bind reader
Итак, мы хотим имитировать session.using_bind
в code_under_test
, чтобы он возвращал session
— это сделает наш тест пройденным.
Мы делаем это, используя patch
, вот так:
@patch("test.database.db.session.using_bind")
def test(mock_bind):
mock_bind.return_value = database.db.session
assert code_under_test() == "success!"
Обратите внимание, что мой код находится в файле с именем test.py
, поэтому мой вызов patch
применяется к модулю test
— вам нужно будет настроить его, чтобы он указывал на тестируемый модуль в вашем собственном коде.
Также обратите внимание, что мне нужно настроить мой фиктивный до, вызывающий тестируемый код.
Возможно, нужно увидеть больше тестируемого кода. Откуда берётся
database
?