测试Flask路由时,如何Mock MySQLdb callproc以模拟存储过程存在?
解决Flask单元测试中模拟MySQL存储过程不存在的问题
你的问题核心在于:当前的Mock没有真正拦截到cursor.callproc的实际数据库调用,导致测试代码还是去真实的测试数据库里查找存储过程,自然会报错。下面给你两种可行的解决方案,帮你彻底解决这个问题:
方案一:精准Mock当前测试用到的Cursor实例
这种方式更聚焦,只针对当前测试用例中的Cursor对象进行Mock,不会影响其他测试的行为:
@unittest.mock.patch('flask_login.utils._get_user') @unittest.mock.patch('flask_sqlalchemy.SQLAlchemy') def test_attendances_management(self, SQLAlchemy, current_user): # 配置当前用户的Mock user = MagicMock() user.role.name = 'Administrator' user.id = 1 current_user.return_value = user # 构建SQLAlchemy及数据库连接的Mock链 sqlalchemy = SQLAlchemy() mock_raw_conn = MagicMock() mock_cursor = MagicMock() # 关键:给Cursor的callproc方法设置Mock返回值,模拟存储过程的执行结果 mock_cursor.callproc.return_value = ((1, 3, 4),) # 把Mock对象串起来 sqlalchemy.engine.raw_connection.return_value = mock_raw_conn mock_raw_conn.cursor.return_value = mock_cursor # 发起测试请求 response = self.client.get('attendances/management/3/2020/11') self.assertEqual(response.status_code, 200) # 可选:验证存储过程是否被正确调用(参数是否符合预期) mock_cursor.callproc.assert_called_once_with("get_project_members", [3, 11, 2020])
方案二:全局Mock MySQLdb的Cursor类
如果你的多个测试用例都需要模拟存储过程调用,可以直接Mock MySQLdb的Cursor基类,这样所有Cursor实例的callproc都会被拦截:
@unittest.mock.patch('flask_login.utils._get_user') @unittest.mock.patch('MySQLdb.cursors.Cursor.callproc') @unittest.mock.patch('flask_sqlalchemy.SQLAlchemy') def test_attendances_management(self, SQLAlchemy, mock_callproc, current_user): # 配置当前用户Mock user = MagicMock() user.role.name = 'Administrator' user.id = 1 current_user.return_value = user # 配置SQLAlchemy相关Mock sqlalchemy = SQLAlchemy() mock_connection = MagicMock() mock_cursor = MagicMock() sqlalchemy.engine.raw_connection.return_value = mock_connection mock_connection.cursor.return_value = mock_cursor # 设置存储过程的模拟返回值 mock_callproc.return_value = ((1, 3, 4),) # 发起测试请求 response = self.client.get('attendances/management/3/2020/11') self.assertEqual(response.status_code, 200) # 验证调用参数 mock_callproc.assert_called_once_with("get_project_members", [3, 11, 2020])
为什么你的原有代码会失败?
你之前的写法sqlalchemy.engine.raw_connection.cursor.callproc("get_project_members", [3, 9, 2020]).return_value是错误的——Mock方法的返回值应该直接设置给方法本身,而不是在"调用"Mock方法后设置。另外你还写错了参数顺序(请求里的月份是11,你写的是9),这也可能导致后续逻辑出问题。
内容的提问来源于stack exchange,提问作者Matija Lukic
相关产品推荐
相关产品推荐

