如何编写pytest模拟Flask路由中的数据库连接与查询结果?
用pytest测试Flask路由并Mock数据库连接与查询
问题背景
我有如下Flask应用路由代码:
# routes.py from flask import jsonify from app.utils.db import db_connection, db_query from typing import List, Dict # 补充缺失的类型导入 @api.route("/some/route", methods=["GET"]) @auth def get_data_for_some_route(**kwargs) -> List[Dict]: # connect to db db_client = db_connection() # Query db for data(注:原代码里的db.query应为db_query函数的笔误) data = db_query(db_client, GET_STUFF) # parse the data example parsed_data = data[0] return jsonify(parsed_data), 200
我想编写pytest测试该路由,同时Mock数据库连接与查询结果,目前写了如下测试代码但仍有困惑:
# test_routes.py import pytest from fixtures import SOME_ROUTE_JSON_DATA from json import loads # 补充缺失的导入 mock_token = "12345" def test_get_data_for_some_route(mocker, client): querystring1 = 'Hello' querystring2 = 'World' # Mock db query function mocked_db_query = mocker.patch('app.utils.database.db_connection') mocked_db_query.return_value = loads(SOME_ROUTE_JSON_DATA) # Call the route response = client.get( f"/some_route", headers={"Authorization": f"{mock_token}"} ) # assert response.json is some value I expect it to be
我不清楚如何在路由内Mock值,希望能忽略数据库连接,指定测试时的返回数据,从而继续测试函数逻辑。
解决方法
1. 明确Mock的正确路径
Mock的核心原则是patch被测试代码实际使用的对象引用,而非原模块路径。路由代码从app.utils.db导入了db_connection和db_query,因此需要patch这两个对象在routes模块中的引用,即app.routes.db_connection和app.routes.db_query。
2. 分别Mock数据库连接与查询
- 数据库连接
db_connection只需返回一个无关紧要的假对象即可,后续查询操作会被Mock覆盖。 - 查询函数
db_query需要设置return_value为预设的测试数据,确保路由内的data变量拿到我们指定的值,从而测试后续解析逻辑。
3. 修正请求路径与细节
路由实际路径是/some/route,测试中的/some_route是错误的,需修正;同时确保@auth装饰器能识别传入的mock_token,若认证逻辑也需Mock,可额外patch认证装饰器。
完整测试代码示例
# test_routes.py import pytest from fixtures import SOME_ROUTE_JSON_DATA from json import loads mock_token = "12345" # 预设测试用的查询返回数据 TEST_DB_DATA = [{"id": 1, "name": "test_sample"}] def test_get_data_for_some_route(mocker, client): # 1. Mock数据库连接,返回假客户端对象 mock_db_conn = mocker.patch("app.routes.db_connection") mock_db_conn.return_value = "fake_db_client" # 任意值均可 # 2. Mock查询函数,返回预设测试数据 mock_db_query = mocker.patch("app.routes.db_query") mock_db_query.return_value = TEST_DB_DATA # 3. 发起正确路径的请求 response = client.get( "/some/route", headers={"Authorization": f"{mock_token}"} ) # 4. 断言响应状态码与返回值 assert response.status_code == 200 assert response.json == TEST_DB_DATA[0] # 与路由内的解析逻辑对应 # 可选:验证Mock对象是否被正确调用 mock_db_conn.assert_called_once() mock_db_query.assert_called_once_with("fake_db_client", "GET_STUFF") # 匹配GET_STUFF常量
关键说明
- 如果路由内的
db.query是调用某个db对象的方法(而非导入的db_query函数),需调整Mock对象:比如从app.utils.db import db的话,要patchapp.routes.db.query,并设置mock_query.return_value = TEST_DB_DATA。 - 通过Mock数据库相关操作,可完全隔离真实数据库,仅测试路由的业务逻辑(数据解析、响应返回)。
内容的提问来源于stack exchange,提问作者says
相关产品推荐
相关产品推荐

