Код: Выделить всё
import sys, pytest
from PyQt5 import QtWidgets
from unittest import mock
class MyLineEdit(QtWidgets.QLineEdit):
def __init__(self, parent):
super().__init__(parent)
self.setPlaceholderText('bubbles')
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Pytest MRE")
self.setMinimumSize(400, 200)
layout = QtWidgets.QVBoxLayout()
qle = MyLineEdit(self)
layout.addWidget(qle)
self.setLayout(layout)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
def test_MyLineEdit_sets_a_title():
mock_window = mock.Mock(spec=QtWidgets.QWidget)
print(f'mock_window.__class__ {mock_window.__class__}') # says "QWidget"
print(f'type(mock_window) {type(mock_window)}') # says "mock.Mock"
with mock.patch('PyQt5.QtWidgets.QLineEdit.setPlaceholderText') as mock_set_placeholder:
# with mock.patch('PyQt5.QtWidgets.QLineEdit.__init__') as mock_super_init:
my_line_edit = MyLineEdit(mock_window)
mock_set_placeholder.assert_called_once()
assert False
Обычно, когда я пытаюсь запустить этот тест, я получаю:
Код: Выделить всё
E TypeError: arguments did not match any overloaded call:
E QLineEdit(parent: Optional[QWidget] = None): argument 1 has unexpected type 'Mock'
E QLineEdit(contents: Optional[str], parent: Optional[QWidget] = None): argument 1 has unexpected type 'Mock'
test_grey_out_qle_exp.py:7: TypeError
Снова и снова, во время моего тестируя приложения PyQt, я обнаружил, что мне нужно передать настоящий QtWidget (или другой реальный объект класса PyQt). Это, в свою очередь, может вызвать всевозможные проблемы, в худшем случае неприятные периодические ошибки «Нарушение прав доступа Windows»… в зависимости от того, от какого типа комбинации реальных объектов PyQt и макетов я пытаюсь получить результаты.
Я хочу каким-то образом замаскировать макет в код PyQt. Я пробовал различные комбинации MagicMock, spec, autospec и т. д. Но код PyQt никогда не обманешь. Похоже, что проверка осуществляется с помощью встроенной функции type(x). Однако я не знаю этого наверняка, так как не могу изучить какой-либо исходный код, поскольку оказывается, что модули PyQt автоматически генерируются из кода C++.
Одна вещь мне пришло в голову: можно ли исправить встроенную функцию type()... ? Вероятно, маловероятное решение, не в последнюю очередь потому, что модуль PyQt, как я подозреваю, не использует код Python при проверке типа. Однако я искал это, но безрезультатно.
PS, как показано в закомментированной строкеock.patch..., одним из возможных обходных путей является начало исправления любые методы суперкласса PyQt, которые вызывают проблемы...
позже: предложение musicamante
Хорошая идея. Я попробовал это:
Код: Выделить всё
class HybridMock(QtWidgets.QWidget, mock.Mock):
def __init__(self, *args, **kwargs):
# super().__init__(*args, **kwargs)
QtWidgets.QWidget.__init__(self, *args, **kwargs)
def test_MyLineEdit_sets_a_title():
# mock_window = mock.Mock(spec=QtWidgets.QWidget)
mock_window = HybridMock()
Подробнее здесь: https://stackoverflow.com/questions/788 ... t-in-qt-me