pytest-mock combined with pytest-qt: call mock after function has executed

37 Views Asked by At

I would like to call the function that is mocked before the mock is called. What is the best way to do this?

main.py

import logging
import sys

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton


class MainWindow(QMainWindow):
    def __init__(self, app: QApplication):
        super().__init__()
        self.app = app
        self.resize(330, 200)
        self.setWindowTitle("Window 1")
        self.button = QPushButton("Button")
        self.setCentralWidget(self.button)
        self.message_printed = False
        def button_clicked() -> None:
            self.display_message("Hello, world!")
        self.button.clicked.connect(button_clicked)

    def display_message(self, msg: str) -> None:
        logging.info(f"Message: {msg}")
        # Some complex code here...
        self.message_printed = True

def main():
    logging.basicConfig(level=logging.INFO)
    app = QApplication(sys.argv)
    window = MainWindow(app)
    window.show()
    app.exec()

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    main()

This test does not pass, since the mock is called instead of the mocked function (not after):

test_main.py:

from PyQt6.QtCore import Qt

from main import MainWindow

def test_message(qtbot, qapp, mocker):
    window = MainWindow(app=qapp)
    qtbot.addWidget(window)
    window.show()
    with qtbot.waitCallback() as callback:
        mocker.patch.object(window, "display_message", callback)
        qtbot.mouseClick(window.button, Qt.MouseButton.LeftButton)
    assert window.message_printed

However, the following test works but I would like to know if there is simpler (more elegant) way to do this:

test_main2.py:

from PyQt6.QtCore import Qt

from main import MainWindow

def test_message(qtbot, qapp, mocker):
    window = MainWindow(app=qapp)
    qtbot.addWidget(window)
    window.show()
    with qtbot.waitCallback() as callback:
        def gen_wrapper():
            original_method = window.display_message
            def wrapper(*args, **kwargs):
                original_method(*args, **kwargs)
                callback(*args, **kwargs)
            return wrapper
        wrapper = gen_wrapper()
        mocker.patch.object(window, "display_message", wrapper)
        qtbot.mouseClick(window.button, Qt.MouseButton.LeftButton)
    assert window.message_printed
0

There are 0 best solutions below