Проблема с мокированием send_request()
в юнит-тестах
У меня возникли проблемы с мокированием функции send_request()
в моих тестах. Несмотря на использование patch
, оригинальная функция send_request()
вызывается, и мок не применяется. Вот соответствующий вывод и код:
Вывод:
Send_click
send_request mock: <function send_request at 0x7f9c2146de40>
send request
Код:
logic.py
def send_request(manager, action_method, url, data=None, params=None, headers=None):
print("send request")
test_ui.py
from ..ui import UserInterface
from unittest.mock import patch, Mock
@patch("ui.send_request")
def test_send_request(mock_send_request, qtbot):
ui = UserInterface()
ui.get_request_data = Mock()
data = QByteArray(data_str_create.encode("utf-8"))
action_method, url, data = ACTIONS_METHODS.POST, QUrl("http://example.com/api"), data
ui.get_request_data.return_value = action_method, url, data
ui.send_click()
mock_send_request.assert_called_once()
Проблема:
send_request()
не замокирован; оригинальная функция выполняется. Это подтверждается появлениемsend request
в выводе и типомfunction
в выводе.AssertionError
в последней строке теста указывает на то, что мок не был применён.
Как используется send_request()
:
ui.py
from logic import handle_response, send_request
class UserInterface(QWidget):
# другие методы
def get_request_data(self):
action_method = self.combo_box.currentText()
json_dict = json.loads(
self.body.toPlainText().encode("utf-8").decode("unicode_escape")
)
json_data = json.dumps(json_dict).encode("utf-8")
data = QByteArray(json_data)
url = QUrl(self.url.text())
return action_method, url, data
def send_click(self):
print("Send_click")
print(f"send_request mock: {send_request}")
send_request(self.rest_manager, *self.get_request_data())
Может кто-нибудь помочь разобраться, почему функция send_request()
не мокируется как ожидалось?
Ответ
Проблема, с которой вы столкнулись, связана с неверной путевой иерархией при использовании декоратора @patch
для замены функции send_request()
. Чтобы корректно замокировать функцию, вам нужно убедиться, что вы указываете правильный путь к функции, которую вы хотите замокировать, относительно того, как она импортируется в вашем коде.
Причина проблемы
Вы используете @patch("ui.send_request")
, чтобы замокировать send_request
, но функция на самом деле импортируется из модуля logic
. Когда вы вызываете send_request
внутри класса UserInterface
, Python ищет её именно в том модуле, из которого она была импортирована, а не в ui
. Поэтому оригинальная функция вызывается вместо замокированной.
Решение
Чтобы исправить эту проблему, вам нужно изменить путь, который вы указываете для замокирования, на путь, соответствующий модулю logic
, откуда импортируется send_request
. Попробуйте заменить строку декоратора на:
@patch("logic.send_request")
Обновленный код теста
Вот как должен выглядеть ваш тестовый метод с исправлениями:
from ..ui import UserInterface
from unittest.mock import patch, Mock
from logic import ACTIONS_METHODS
from PyQt5.QtCore import QByteArray
from PyQt5.QtCore import QUrl
@patch("logic.send_request") # Изменен путь для правильного замокирования
def test_send_request(mock_send_request, qtbot):
ui = UserInterface()
ui.get_request_data = Mock()
data_str_create = '{"key": "value"}' # добавлено для примера
data = QByteArray(data_str_create.encode("utf-8"))
action_method, url = ACTIONS_METHODS.POST, QUrl("http://example.com/api")
# Возвращаем действие и URL до того, как будет вызвана send_click
ui.get_request_data.return_value = action_method, url, data
ui.send_click()
mock_send_request.assert_called_once() # Проверяем, был ли вызван замокированный метод
Дополнительные рекомендации:
-
Проверьте структуру импортов: Убедитесь, что
send_request
импортируется вui.py
именно изlogic
, и проверьте, что остальная часть кода не создает конфликтов с именами. -
Логирование: Используйте
print()
для отладки, чтобы убедиться, что Mock работает, до того, как дошли до вызоваsend_click
. - Отключение других декораторов: Если в вашем проекте используются другие декораторы или фреймворки, это может повлиять на поведение теста. Убедитесь, что вы не вызываете другие модули, влияющие на замокированные функции.
Следуя этим шагам, вы должны успешно замокировать функцию send_request
и избежать вызова оригинальной версии в ваших тестах.