模拟 PyQt 方法 [英] Mock a PyQt Method

查看:42
本文介绍了模拟 PyQt 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个继承自 PyQT5 类 QWidget 和 Ui_Dialog 的现有类.

I have an existing class which inherits from the PyQT5 classes QWidget and Ui_Dialog.

我想使用该类的一些与 GUI 完全无关的功能.因此,我试图模拟出相关的位,例如 __init__ 函数,它有很多特定于 GUI 的代码.类中还有一个特定的方法需要覆盖(_getSqlQuery).

I want to use some functionality of the class which is not at all related to the GUI. I have therefore tried to mock out the relevant bits, such as the __init__ function which has a lot of GUI-specific code. There is also a specific method in the class which needs overriding (_getSqlQuery).

class TestPyQgs(unittest.TestCase):
  def test_comment_parsing(self):
    query = "SELECT * FROM test"
    with patch.object(DlgSqlWindow, "__init__", lambda x, y, z: None):
      with patch.object(DlgSqlWindow, "_getSqlQuery", return_value=query):
        a = DlgSqlWindow(None,None)
        self.assertEqual(a.parseSQL(), query)

不幸的是,这不起作用,因为从 QtWidget 继承的任何东西(如 DlgSqlWindow 所做的)都必须在基类上调用 init,所以我得到 DlgSqlWindow 类型的超类 __init__() 从未被调用.有没有理智的方法来做到这一点?否则我应该尝试重构代码以将 GUI 从功能中分离出来,或者也对 GUI 进行单元测试,我宁愿不这样做,因为我希望单元测试尽可能紧凑.

Unfortunately this doesn't work because anything that inherits from QtWidget (as DlgSqlWindow does) has to call init on the Base Class, so I get super-class __init__() of type DlgSqlWindow was never called. Is there no sane way of doing this? Otherwise should I try and refactor the code to split GUI from functionality, or do a unit test on the GUI as well, which I would rather not do as I want the unit test to be as tight as possible.

推荐答案

一种可能的解决方案是调用没有太多逻辑的超级QWidget:

One possible solution is to just call the super QWidget who doesn't have much logic:

import unittest
from unittest.mock import patch

from PyQt5 import QtWidgets


class Ui_Dialog(object):
    def setupUi(self, dialog):
        pass


class DlgSqlWindow(QtWidgets.QWidget, Ui_Dialog):
    def _getSqlQuery(self):
        pass

    def parseSQL(self):
        return "SELECT * FROM test"


def init(self, *args):
    QtWidgets.QWidget.__init__(self)
    # self.setupUi(self)


class TestPyQgs(unittest.TestCase):
    def test_comment_parsing(self):
        app = QtWidgets.QApplication([])
        query = "SELECT * FROM test"
        with patch.object(DlgSqlWindow, "__init__", init):
            with patch.object(DlgSqlWindow, "_getSqlQuery", return_value=query):
                a = DlgSqlWindow(None, None)
                self.assertEqual(a.parseSQL(), query)


if __name__ == "__main__":
    unittest.main()

但正如您所指出的,最佳解决方案是重构您的代码,因为您似乎将业务逻辑与 GUI 混合在一起,如您所见,这会导致一些不便且不可维护.

But as you point out, the optimal solution is to refactor your code since it seems that you are mixing business logic with the GUI which, as you can see, causes several inconveniences and is not maintainable.

这篇关于模拟 PyQt 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆