如何为MagicMock模拟的函数添加参数实现动态返回值
基于参数动态返回Mock结果的解决方案
你想要根据filter方法的传入参数动态返回不同结果,直接通过configure_mock的属性字典无法实现,得用side_effect处理参数判断,同时适配SQLAlchemy的text()包装逻辑,具体实现如下:
核心思路
原代码的调用链是self._session.query(Table1).filter(text(filter_exp)).all(),我们需要:
- 给
filter方法设置side_effect,根据传入的TextClause对象(即text(filter_exp)的返回值)的内容,返回对应的mock对象 - 每个对应参数的mock对象,其
all()方法返回预设的结果
完整测试代码
def test_filter(): # 1. 准备不同的mock返回对象 mock_object_1 = MagicMock() mock_object_2 = MagicMock() # 2. 定义filter方法的side_effect:根据text参数返回对应mock def filter_side_effect(filter_clause): # 提取text()包装的实际SQL字符串内容 filter_exp = str(filter_clause) # 创建对应结果的mock result_mock = MagicMock() if filter_exp == "WHERE x = 1": result_mock.all.return_value = [mock_object_1] elif filter_exp == "WHERE x = 2": result_mock.all.return_value = [mock_object_2] else: # 处理未匹配的参数,可返回空列表或抛出异常 result_mock.all.return_value = [] return result_mock # 3. 逐层配置mock_session的链式调用 db_connection = DBConnection("", "", 0, "", "") mock_session = MagicMock() # query返回的mock对象,其filter方法使用上面定义的side_effect mock_query = MagicMock() mock_query.filter.side_effect = filter_side_effect mock_session.query.return_value = mock_query # 替换真实的_session为mock setattr(db_connection, "_session", mock_session) # 4. 验证不同参数的返回结果 assert db_connection.table_filter("WHERE x = 1") == [mock_object_1] assert db_connection.table_filter("WHERE x = 2") == [mock_object_2] assert db_connection.table_filter("WHERE x = 3") == []
关键细节说明
- 原代码中
filter接收的是text(filter_exp)返回的TextClause对象,所以需要用str(filter_clause)提取实际的SQL片段来判断参数 side_effect可以是一个函数,函数的参数就是被mock方法接收到的参数,返回值就是该方法的返回结果- 链式调用的mock需要逐层配置:先mock
session.query返回mock_query,再给mock_query.filter设置side_effect,最后在side_effect中给每个分支的result_mock.all设置返回值
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

