Movatterモバイル変換


[0]ホーム

URL:


跳转至
Join theFastAPI Cloud waiting list 🚀
Follow@fastapi onX (Twitter) to stay updated
FollowFastAPI onLinkedIn to stay updated
Subscribe to theFastAPI and friends newsletter 🎉
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor

异步测试

🌐 由 AI 与人类协作翻译

本翻译由人类引导的 AI 生成。🤝

可能存在误解原意或不够自然等问题。🤖

你可以通过帮助我们更好地引导 AI LLM来改进此翻译。

英文版本

您已经了解了如何使用TestClient 测试FastAPI 应用程序。但是到目前为止,您只了解了如何编写同步测试,而没有使用async 异步函数。

在测试中能够使用异步函数可能会很有用,比如当您需要异步查询数据库的时候。想象一下,您想要测试向 FastAPI 应用程序发送请求,然后验证您的后端是否成功在数据库中写入了正确的数据,与此同时您使用了异步的数据库的库。

让我们看看如何才能实现这一点。

pytest.mark.anyio

如果我们想在测试中调用异步函数,那么我们的测试函数必须是异步的。 AnyIO 为此提供了一个简洁的插件,它允许我们指定一些测试函数要异步调用。

HTTPX

即使您的FastAPI 应用程序使用普通的def 函数而不是async def ,它本质上仍是一个async 异步应用程序。

TestClient 在内部通过一些“魔法”操作,使得您可以在普通的def 测试函数中调用异步的 FastAPI 应用程序,并使用标准的 pytest。但当我们在异步函数中使用它时,这种“魔法”就不再生效了。由于测试以异步方式运行,我们无法在测试函数中继续使用TestClient

TestClient 是基于HTTPX 的。幸运的是,我们可以直接使用它来测试API。

示例

举个简单的例子,让我们来看一个更大的应用测试中描述的类似文件结构:

.├── app│   ├── __init__.py│   ├── main.py│   └── test_main.py

文件main.py 将包含:

fromfastapiimportFastAPIapp=FastAPI()@app.get("/")asyncdefroot():return{"message":"Tomato"}

文件test_main.py 将包含针对main.py 的测试,现在它可能看起来如下:

importpytestfromhttpximportASGITransport,AsyncClientfrom.mainimportapp@pytest.mark.anyioasyncdeftest_root():asyncwithAsyncClient(transport=ASGITransport(app=app),base_url="http://test")asac:response=awaitac.get("/")assertresponse.status_code==200assertresponse.json()=={"message":"Tomato"}

运行测试

您可以通过以下方式照常运行测试:

$pytest---> 100%

详细说明

这个标记@pytest.mark.anyio 会告诉 pytest 该测试函数应该被异步调用:

importpytestfromhttpximportASGITransport,AsyncClientfrom.mainimportapp@pytest.mark.anyioasyncdeftest_root():asyncwithAsyncClient(transport=ASGITransport(app=app),base_url="http://test")asac:response=awaitac.get("/")assertresponse.status_code==200assertresponse.json()=={"message":"Tomato"}

提示

请注意,测试函数现在用的是async def,而不是像以前使用TestClient 时那样只是def

我们现在可以使用应用程序创建一个AsyncClient ,并使用await 向其发送异步请求。

importpytestfromhttpximportASGITransport,AsyncClientfrom.mainimportapp@pytest.mark.anyioasyncdeftest_root():asyncwithAsyncClient(transport=ASGITransport(app=app),base_url="http://test")asac:response=awaitac.get("/")assertresponse.status_code==200assertresponse.json()=={"message":"Tomato"}

这相当于:

response=client.get('/')

...我们曾经通过它向TestClient 发出请求。

提示

请注意,我们正在将 async/await 与新的AsyncClient 一起使用——请求是异步的。

警告

如果您的应用程序依赖于生命周期事件,AsyncClient 将不会触发这些事件。为了确保它们被触发,请使用florimondmanca/asgi-lifespan 中的LifespanManager

其他异步函数调用

由于测试函数现在是异步的,因此除了在测试中向 FastAPI 应用程序发送请求之外,您现在还可以调用(和使用await 等待)其他async 异步函数,就和您在代码中的其他任何地方调用它们的方法一样。

提示

如果您在测试程序中集成异步函数调用的时候遇到一个RuntimeError: Task attached to a different loop 的报错(例如,使用MongoDB 的 MotorClient 时),请记住,只能在异步函数中实例化需要事件循环的对象,例如在@app.on_event("startup") 回调中初始化。


[8]ページ先頭

©2009-2026 Movatter.jp