Как макетировать объекты класса Python?
Допустим, я следующий класс;
class CompositionClass(object):
def __init__(self):
self._redis = Redis()
self._binance_client = BinanceClient()
def do_processing(self, data):
self._redis.write(data)
self._binance_client.buy(data.amount_to_buy)
# logic to actually unittest
return process_val
У меня есть другие объекты, которые вызывают внешний API как композицию в моем ComplexClass
, Когда я тестирую логику do_processing
Я не хочу называть эти дорогие вызовы API. Я проверил полностью в SO и Google на предмет юнит-тестирования; Все примеры просты, но не очень полезны. В моем случае, как я могу использовать unittest.mock
издеваться над этими объектами?
2 ответа
Один из способов издеваться над Redis
а также BinanceClient
классы, чтобы использовать patch
декоратор в вашем тестовом классе, например:
from unittest import TestCase
from unittest.mock import patch
from package.module import CompositionClass
class TestCompositionClass(TestCase):
@patch('package.module.BinanceClient')
@patch('package.module.Redis')
def test_do_processing(self, mock_redis, mock_binance):
c = CompositionClass()
data = [...]
c.do_processing(data)
# Perform your assertions
# Check that mocks were called
mock_redis.return_value.write.assert_called_once_with(data)
mock_binance.return_value.buy.assert_called_once_with(data.amount_to_buy)
Обратите внимание, что путь, указанный в @patch
путь к модулю, содержащему CompositionClass
и его импорт для Redis
а также BinanceClient
, Исправление происходит в этом модуле, а не в модуле, содержащем Redis
а также BinanceClient
Сами реализации.
Вам нужно установить значение, которое должно быть возвращено вашим вызовом API, этой функции:
from unittest.mock import MagicMock
class Tester(unittest.TestCase):
def setUp(self):
pass
def test_do_processing(self):
self.API_function = MagicMock(return_value='API_response')
# test logic