You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pytest-asyncio运行多个异步测试时出现事件循环错误

解决pytest-asyncio多异步测试循环不匹配问题

错误原因

pytest-asyncio默认每个测试函数会创建独立的事件循环,而你的数据库连接(由get_db_connection返回)绑定了第一个测试的事件循环,当第二个测试使用新循环时,调用该连接的异步操作就会触发RuntimeError: Task got Future attached to a different loop错误。

解决方案

方案1:让所有测试共享同一个事件循环

你可以通过两种方式配置共用循环:

  • 给测试用例指定循环作用域
    给每个@pytest.mark.asyncio装饰器加上loop_scope参数,指定会话级或模块级共用循环:
    @pytest.mark.asyncio(loop_scope="session")
    async def test_foo():
        client = await get_db_connection()
        # ... 测试代码
    
    @pytest.mark.asyncio(loop_scope="session")
    async def test_error_foo():
        client = await get_db_connection()
        # ... 测试代码
    
  • 通过fixture定义会话级循环
    在项目的conftest.py文件中添加以下fixture,强制所有测试使用同一个会话级事件循环:
    import pytest
    import asyncio
    
    @pytest.fixture(scope="session")
    def event_loop():
        loop = asyncio.new_event_loop()
        yield loop
        loop.close()
    

方案2:确保每个测试使用独立的数据库连接

检查get_db_connection是否有缓存逻辑(比如单例、lru_cache装饰器),如果存在缓存,移除后让每个测试都创建全新的连接:

# 移除缓存,每次调用创建新连接
import asyncpg

async def get_db_connection():
    return await asyncpg.connect(dsn="你的数据库DSN")

更规范的做法是用pytest fixture管理数据库连接,确保每个测试的连接独立且自动清理:

# 在conftest.py中定义fixture
import pytest
import asyncpg

@pytest.fixture(scope="function")
async def db_client():
    conn = await asyncpg.connect(dsn="你的数据库DSN")
    yield conn
    await conn.close()

然后在测试用例中直接注入这个fixture:

@pytest.mark.asyncio
async def test_foo(db_client):
    user = await db_client.fetch("SELECT ...")
    response = await FunctionUnderTest(db=db_client, ...args)
    assert response.id is not None

@pytest.mark.asyncio
async def test_error_foo(db_client):
    with pytest.raises(MissingRequiredError):
        await FunctionUnderTest(db=db_client, ...args)

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 00:50:21