如何使用MagicMock模拟SQLAlchemy的limit和offset函数?
问题:如何为SQLAlchemy的Limit/Offset链式调用编写单元测试?
我是Python单元测试新手,正在尝试为SQLAlchemy的Limit Offset函数编写单元测试,不确定如何模拟session.query(table).limit(20).offset(20)这段链式调用代码。我用unittest.mock.patch模拟load_session函数,但试了几种语法都没效果,相关代码如下:
源代码
def execute(): ... db2_engine = get_db2_engine() session = load_session(db2_engine) result_set = session.query(Table).limit(20).offset(20) session.close() ...
现有测试代码
import unittest from unittest.mock import MagicMock, patch def setUp(self): self.worker = MyClass( ... ) @patch("source_class.load_session") def test_execute(self, mock_load_session): ... mock_session = MagicMock() mock_session.query.return_value = MagicMock() mock_session.query.return_value.limit.return_value = MagicMock() mock_session.query.return_value.limit.return_value.offset.return_value = [...] mock_load_session.return_value = mock_session ... self.worker.execute() ...
解决方案
你的核心思路是正确的,可以通过拆分链式调用的Mock对象来简化写法,同时增加断言验证确保代码执行符合预期:
修改后的测试代码
import unittest from unittest.mock import MagicMock, patch from source_class import MyClass, Table # 导入实际的类和表模型 class TestMyClass(unittest.TestCase): def setUp(self): self.worker = MyClass( # 这里填写MyClass的初始化参数 ) @patch("source_class.load_session") def test_execute(self, mock_load_session): # 分步骤构建链式调用的Mock mock_offset = MagicMock(return_value=[{"id": 1}, {"id": 2}]) # 模拟最终返回的结果集 mock_limit = MagicMock() mock_limit.offset.return_value = mock_offset mock_query = MagicMock() mock_query.limit.return_value = mock_limit mock_session = MagicMock() mock_session.query.return_value = mock_query mock_load_session.return_value = mock_session # 执行被测试方法 self.worker.execute() # 验证链式调用的参数是否符合预期 mock_session.query.assert_called_once_with(Table) mock_query.limit.assert_called_once_with(20) mock_limit.offset.assert_called_once_with(20) # 验证session资源是否正确释放 mock_session.close.assert_called_once()
关键说明
- 链式Mock拆分:把
query、limit、offset的Mock对象分开定义,比嵌套写法更清晰,也方便后续做针对性断言。 - 结果模拟:给
offset的Mock设置返回值,让被测试方法里的result_set能拿到预设的模拟数据,覆盖后续逻辑的测试场景。 - 断言验证:通过
assert_called_once_with确认每个方法的调用参数完全符合预期,避免只Mock返回值却没验证调用逻辑的问题。 - 资源释放检查:别忘了断言
session.close()被调用,确保代码的资源回收逻辑正常执行。
另外注意:你的源代码里有笔误,db2_session.close()应该改为session.close()(前面变量定义是session = load_session(...)),否则测试里的close断言会失败。
内容的提问来源于stack exchange,提问作者user3595026
相关产品推荐
相关产品推荐

