Вот тот же тест с использованием pytest и модуля:
def test(mocker):
mock_db = mocker.MagicMock(name='db')
mocker.patch('db_class.db', new=mock_db)
expected_result = [5, 10]
mock_db.a.return_value.__enter__.return_value.b.fetch.return_value = expected_result
foo = db_class.Foo()
result = foo.method()
assert result == expected_result
Вы можете найти то, как я написал тест, более интересным, чем сам тест — я создал библиотеку Python чтобы помочь мне с синтаксисом.
Вот как я подошел к вашей проблеме систематическим образом:
Начнем с нужного вам теста и моей вспомогательной библиотеки:
import db_class
from mock_autogen.pytest_mocker import PytestMocker
def test(mocker):
# this would output the mocks we need
print(PytestMocker(db_class).mock_modules().prepare_asserts_calls().generate())
# your original test, without the mocks
expected_result = [5,10]
foo = db_class.Foo()
result = foo.method()
assert result == expected_result
Теперь тест явно не пройден (AttributeError: module 'db' has no attribute 'a'
), но вывод на печать полезен:
# mocked modules
mock_db = mocker.MagicMock(name='db')
mocker.patch('db_class.db', new=mock_db)
# calls to generate_asserts, put this after the 'act'
import mock_autogen
print(mock_autogen.generator.generate_asserts(mock_db, name='mock_db'))
Теперь я помещаю моки перед вызовом Foo()
и generate_asserts
после, как раз перед вашим утверждением, вот так (нет необходимости в предыдущей печати, поэтому я удалил ее):
def test(mocker):
# mocked modules
mock_db = mocker.MagicMock(name='db')
mocker.patch('db_class.db', new=mock_db)
# your original test, without the mocks
expected_result = [5,10]
foo = db_class.Foo()
result = foo.method()
# calls to generate_asserts, put this after the 'act'
import mock_autogen
print(mock_autogen.generator.generate_asserts(mock_db, name='mock_db'))
assert result == expected_result
Теперь утверждение терпит неудачу (AssertionError: assert <MagicMock name='db.a().__enter__().b.fetch()' id='139996983259768'> == [5, 10]
), но мы еще раз получили ценную информацию:
mock_db.a.return_value.__enter__.assert_called_once_with()
mock_db.a.return_value.__enter__.return_value.b.fetch.assert_called_once_with()
mock_db.a.return_value.__exit__.assert_called_once_with(None, None, None)
Обратите внимание на вторую строку, это почти то, что вам нужно издеваться. С небольшим изменением он будет выглядеть как mock_db.a.return_value.__enter__.return_value.b.fetch.return_value = expected_result
, и с этим мы можем получить окончательный вариант теста:
def test(mocker):
mock_db = mocker.MagicMock(name='db')
mocker.patch('db_class.db', new=mock_db)
expected_result = [5, 10]
mock_db.a.return_value.__enter__.return_value.b.fetch.return_value = expected_result
foo = db_class.Foo()
result = foo.method()
assert result == expected_result
Вы можете добавить дополнительные автоматически сгенерированные утверждения или изменить их, включив в них дополнительные утверждения, если сочтете это полезным.
person
Peter K
schedule
06.08.2019