Есть разные способы сделать это.Ниже приведены приемы, которые я сейчас использую с python2 и python3.
Предположим, мы собираемся смоделировать функцию с именем get_val
для возврата yes
:
# data.py
def get_val():
return 'no'
Я просто буду использовать setUp
в демонстрационном коде, но тот же трюк должен работать и с setUpClass
.
1.Самый простой способ: использовать макет на тестовом классе
# test_data.py
# mock value is fixed
@patch('data.get_val', MagicMock(return_value='yes')) # fixed value
class TestFoo(TestCase):
def setUp(self):
print(data.get_val()) # no
def test_case(self):
print(data.get_val()) # yes
# mock value set by each test case
@patch('data.get_val')
class TestBar(TestCase):
def setUp(self):
print(data.get_val()) # no
def test_case(self, mock_get_val):
mock_get_val.return_value = 'yes' # set value in each case
print(data.get_val()) # yes
Плюсы:
Минусы:
- Цель не смоделирована в
setUp
- Вы можете выбрать либо макет цели с фиксированным значением, либо предоставить значение макета в каждом отдельном тестовом случае.Никакой микс не использует вообще.
2.Самый гибкий способ: запустить макет вручную
# test_data.py
class TestCool(TestCase):
def setUp(self):
self.mocks = [patch('data.get_val', MagicMock(return_value='yes'))] # fixed value
for mock in self.mocks:
mock.start()
print(data.get_val()) # yes
def tearDown(self):
for mock in self.mocks:
mock.stop()
def test_case(self):
print(data.get_val()) # yes
def test_case_cool(self):
self.mocks[0].return_value = 'cool' # override the mock only for this case
print(data.get_val()) # cool
Плюсы:
- Вы можете получить макеты работ внутри
setUp
s - Вы можете смешать использованиемакет с предварительно заданными фиксированными значениями или предоставление значений макетов в каждом тестовом случае
- Проще управлять тоннами макетов, поскольку вы можете написать код для управления ими.
Минусы:
- Пришлось бы написать больше кода для даже простых задач.
Бонусный совет:
Не используйте patch
на setUp
напрямую,потому что изменение подписи setUp
s вызывает жалобу PyCharm на это:
Подпись метода 'TestMockedSetup.setUp ()' не соответствует подписи базового метода в классе 'TestCase'
А если серьезно, макет работает только внутри setUp
и в ваших тестовых примерах будет восстановлен как немодированный, что, вероятно, не то, что вам нужно.