直接用requests.post发GraphQL请求最可靠,关键在于构造合法JSON体(query和variables字段)、设置Content-Type: application/json,并用fixture复用session;遇GraphQLError需根据errors.locations和message定位schema或resolver问题。

pytest怎么调用GraphQL接口做集成测试
直接用 requests.post 发请求最可靠,别被 pytest 插件带偏——多数 GraphQL 测试不需要额外插件,尤其当你只验证后端逻辑或 API 行为时。
关键不是“用什么框架”,而是「构造合法的 GraphQL 请求体」+「校验响应结构」。常见错误是把 query 当成 URL 参数传,或者漏掉 Content-Type: application/json 导致服务端解析失败。
- query 必须放在 JSON body 的
"query"字段里,变量(如有)放"variables"字段 - 务必设置
headers={"Content-Type": "application/json"},否则 Flask/Starlette/FastAPI 可能返回 400 - 用
json.dumps()序列化请求体,别手动拼字符串(容易引号错乱) - 测试前确保 GraphQL 服务已启动(比如用
pytest --base-url=http://localhost:8000传入地址)
示例:
import requests
import json
def test_user_query():
url = "http://localhost:8000/graphql"
query = '''
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
'''
response = requests.post(
url,
json={"query": query, "variables": {"id": "1"}},
headers={"Content-Type": "application/json"}
)
assert response.status_code == 200
data = response.json()
assert "data" in data
assert data["data"]["user"]["name"] == "Alice"
如何复用 client 实例避免重复创建 session
每次测都新建 requests.Session() 没问题,但如果你有鉴权头、cookie 或需要连接复用(比如测批量请求),就该封装一个 fixture。
立即学习“Python免费学习笔记(深入)”;
pytest fixture 是最自然的解法——它比全局变量安全,比类属性清晰,还能自动管理生命周期。
- 用
@pytest.fixture返回带默认 headers 的requests.Session实例 - 在 fixture 里注入 token(比如从环境变量或登录接口获取),避免每个 test 重复登录
- 注意 session 不会自动关闭,加
yield+session.close()更稳妥 - 不要在 fixture 里硬编码 URL,用
pytest.config.getoption("--base-url")动态传入
示例 fixture:
@pytest.fixture
def gql_client():
session = requests.Session()
session.headers.update({"Authorization": "Bearer test-token"})
yield session
session.close()
def test_create_post(gql_client):
resp = gql_client.post(
"http://localhost:8000/graphql",
json={"query": "mutation { createPost(title: \"Test\") { id } }"}
)
assert resp.json()["data"]["createPost"]["id"]
遇到 GraphQLError 怎么定位是 schema 还是 resolver 问题
当响应里出现 "errors" 字段,先别急着改测试代码——90% 是你发的 query 本身不合法,或字段名/类型写错了。
重点看 errors[0]["locations"] 提供的行列号,它指向的是服务端解析后的 AST 位置,不是你原始字符串的位置(尤其用了三引号或 f-string 时)。
- 错误信息里含
"message": "Cannot query field ..."→ schema 里没定义该字段,检查 SDL 或 resolver 注册 - 含
"Unknown type"或"Expected type ..."→ query 中标量/输入类型和 schema 不匹配(比如传了String却要ID) - 含
"Internal server error"且无 stacktrace → resolver 抛了未捕获异常,需查服务端日志 - 用
print(response.json())配合断点,别只看 status_code —— GraphQL 协议规定即使出错也返回 200
要不要用 pytest-graphql 或 gql 这类库
没必要,除非你在写大量复杂 mutation 并需要自动生成变量类型校验。对绝大多数后端集成测试,它们只是多一层抽象、少一点控制。
gql 库主打 client 端查询执行(比如 Electron 桌面应用),在 pytest 里用反而增加依赖和学习成本;pytest-graphql 停更多年,不支持现代 ASGI 服务(如 Strawberry + Starlette)。
- 纯 HTTP 测试:坚持用
requests,稳定、调试直观、报错明确 - 需要 mock 服务端响应:用
responses或pytest-mockpatchrequests.post,别 mock GraphQL 层抽象 - 真要类型安全:用
graphql-codegen生成 Python types,再配合pydantic校验响应,而不是换测试库
真正容易被忽略的点是:GraphQL 响应里的 "data" 和 "errors" 是并存的(partial success),测试断言时得同时处理两者,不能只查 data 是否存在。


















