如何用pytest-asyncio测试调用Tenor API的Python异步函数?
问题分析与解决方案
你的问题存在两个核心问题:测试环境下API请求返回400错误,以及异步函数中误用同步HTTP库,下面逐个解决:
1. 解决测试时400错误的问题
400状态码表示请求参数或身份验证不合法,优先排查这几个方向:
- 环境变量未正确加载:单元测试环境中,
os.getenv可能读不到TENOR_API_KEY和TENOR_API_CLIENT,导致请求缺少合法密钥。可以用pytest的monkeypatchfixture模拟环境变量,同时固定get_gif_params的返回值,避免依赖外部逻辑:@pytest.mark.asyncio async def test_gif(monkeypatch): # 模拟API密钥和客户端ID monkeypatch.setenv("TENOR_API_KEY", "your_test_api_key") monkeypatch.setenv("TENOR_API_CLIENT", "your_test_client_id") # 固定查询参数,避免测试受外部逻辑影响 monkeypatch.setattr("your_module.get_gif_params", lambda: "test_query") gif = await get_gif() assert isinstance(gif, str) assert gif.endswith(".gif") - 查询参数不合法:测试时
get_gif_params()可能返回空字符串、未转义的特殊字符,导致Tenor API拒绝请求。可以先打印该函数的返回值,确认参数符合API要求。
2. 修复异步函数中同步HTTP调用的问题
你定义了异步函数get_gif,但内部用了同步的requests.get,这会阻塞事件循环,违背异步编程的设计初衷。换成异步HTTP库aiohttp才是正确的做法:
修改后的异步函数代码
import aiohttp import os async def get_gif(): api_key = os.getenv('TENOR_API_KEY') client_key = os.getenv('TENOR_API_CLIENT') query = get_gif_params() # 使用aiohttp发起异步请求 async with aiohttp.ClientSession() as session: # 用params参数自动处理URL编码,避免特殊字符导致的请求错误 params = { "q": query, "key": api_key, "client_key": client_key, "limit": 1 } async with session.get("https://tenor.googleapis.com/v2/search", params=params) as r: if r.status == 200: data = await r.json() return data['results'][0]["media_formats"]["mediumgif"]['url']
额外优化建议
- 添加异常处理:当前代码在请求失败时返回
None,容易引发后续逻辑报错。建议添加错误分支,抛出异常或返回默认值:async def get_gif(): # ... 前面代码 ... async with session.get(...) as r: if r.status == 200: # ... 解析逻辑 ... return gif else: raise ValueError(f"Tenor API请求失败,状态码: {r.status}")
内容的提问来源于stack exchange,提问作者Ethan Ansel-Kelly
相关产品推荐
相关产品推荐

