PyQt中如何Mock QResizeEvent并传入resizeEvent方法?
解决PyQt中resizeEvent测试的类型检查问题
问题场景
要验证ResultsTableView的resizeEvent方法是否按比例设置列宽(第一列20%、第二列80%),原测试代码尝试用mock事件对象手动调用resizeEvent,但触发类型错误:
E TypeError: resizeEvent(self, e: QResizeEvent): argument 1 has unexpected type 'Mock'
即使使用mock.MagicMock(spec=QtGui.QResizeEvent)也无法绕过PyQt的类型校验。
原测试代码:
def test_table_resize_event_sets_column_widths(): table = results_table_classes.ResultsTableView(None) with mock.patch.object(table, 'setColumnWidth') as mock_set: mock_event = mock.Mock() mock_size = mock.Mock() mock_event.size = mock.Mock(return_value=mock_size) mock_size.width = mock.Mock(return_value=300) table.resizeEvent(mock_event) assert mock_set.call_args_list[0].args == (0, int(300 * 0.20)) assert mock_set.call_args_list[1].args == (1, int(300 * 0.80))
对应的resizeEvent实现:
def resizeEvent(self, event): width = event.size().width() self.setColumnWidth(0, int(width * 0.20)) # 20% Width Column self.setColumnWidth(1, int(width * 0.80)) # 80% Width Column
解决方案
利用pytest_qt的qtbot fixture,实际调整控件尺寸触发真实的resize事件,绕过PyQt的类型校验:
修改后的测试代码
def test_table_resize_event_sets_column_widths(qtbot): # 创建表格控件并交由qtbot管理 table = results_table_classes.ResultsTableView(None) qtbot.addWidget(table) # 显示控件以确保能接收resize事件 table.show() # 设置目标宽度,调整控件尺寸触发resizeEvent target_width = 300 table.resize(target_width, table.height()) # 直接断言列宽的实际值 assert table.columnWidth(0) == int(target_width * 0.20) assert table.columnWidth(1) == int(target_width * 0.80)
说明
- PyQt的事件处理方法(如
resizeEvent)对参数类型有严格校验,必须传入真实的QResizeEvent实例,mock对象无法通过校验。 - 使用
qtbot.addWidget()管理控件,确保其事件循环正常运行;调用table.resize()会自动触发真实的resizeEvent,无需手动调用方法。 - 直接断言列宽的实际值,比mock
setColumnWidth更贴近真实场景,能同时验证方法调用和结果正确性。
内容的提问来源于stack exchange,提问作者mike rodent
相关产品推荐
相关产品推荐

