使用initializer和finalizer配置FastAPI+Tortoise ORM的pytest测试报错,如何解决?
问题:FastAPI + Tortoise ORM 测试报错
asyncpg.exceptions._base.InterfaceError 按照Tortoise ORM文档编写的测试配置文件如下:
import pytest from fastapi.testclient import TestClient from tortoise.contrib.test import finalizer, initializer import app.main as main from app.core.config import settings @pytest.fixture(scope="session", autouse=True) def initialize_tests(request): db_url = "postgres://USERNAME_HERE:SECRET_PASS_HERE@127.0.0.1:5432/test" initializer( [ "app.models", ], db_url=db_url, app_label="models" ) print("initialize_tests") request.add_finaliser(finalizer) @pytest.fixture(scope="session") def client(): app = main.create_application() with TestClient(app) as client: print("client") yield client
测试文件内容:
def test_get(client): response = client.get("/v1/url/") assert response.status_code == 200
运行测试时出现错误:
asyncpg.exceptions._base.InterfaceError: cannot perform operation: another operation is in progress
希望继续使用initializer和finalizer完成测试配置,而非手动实现的方式,请问如何解决该错误?
解决方案
1. 安装依赖
先安装pytest-asyncio,统一管理测试的异步事件循环:
pip install pytest-asyncio
2. 修改测试配置文件
将初始化fixture改为异步模式,复用测试的主事件循环,避免多循环导致的连接池冲突:
import asyncio import pytest import pytest_asyncio from fastapi.testclient import TestClient from tortoise.contrib.test import finalizer, initializer import app.main as main @pytest_asyncio.fixture(scope="session", autouse=True) async def initialize_tests(): db_url = "postgres://USERNAME_HERE:SECRET_PASS_HERE@127.0.0.1:5432/test" # 使用测试的主事件循环初始化Tortoise initializer( ["app.models"], db_url=db_url, app_label="models", loop=asyncio.get_running_loop() ) yield # 测试会话结束后执行清理 finalizer() @pytest.fixture(scope="session") def client(): app = main.create_application() with TestClient(app) as client: yield client
3. 核心原因与说明
报错根源在于:同步的initialize_tests fixture会创建独立的事件循环初始化Tortoise,而TestClient调用异步接口时会启动另一个事件循环,两个循环共用同一个连接池就会触发并发操作冲突。
修改后的配置通过以下两点解决问题:
- 用
pytest_asyncio.fixture将初始化fixture改为异步模式,运行在测试的主事件循环中。 - 初始化时指定
loop=asyncio.get_running_loop(),强制Tortoise使用测试的主循环,确保连接池在单一循环内被使用。
内容的提问来源于stack exchange,提问作者Ming Linfeng
相关产品推荐
相关产品推荐

