'pytest-asyncio has a closed event loop, but only when running all tests

I have a test to verify an exception is thrown from an async response, which I'm using pytest-asyncio version 0.10.0 to run.

Code is basically:

class TestThis:
    @pytest.mark.asyncio
    def test_the_thing(self):
       arg1 = "cmd"
       arg2 = "second command"
       with pytest.raises(CustomException):
           await do_thing(arg1, arg2)

Now the really weird thing is this test works fine if I run it alone, or if I run the class alone. However when I run all tests (pytest at the project root), it fails every time with a runtime error, saying the loop is closed.



Solution 1:[1]

https://pypi.org/project/pytest-asyncio/

You can apparently override pytest-asyncio's version of the event loop fixture. They have it like this:

@pytest.fixture
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop
    loop.close()

I have it like this:

@pytest.fixture
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop
    cleanly_shutdown(loop)

Or in other cases like this:

@pytest.fixture
def event_loop():
    yield asyncio.get_event_loop()

def pytest_sessionfinish(session, exitstatus):
    asyncio.get_event_loop().close()

These docs are very helpful: https://docs.pytest.org/en/latest/reference/reference.html?highlight=sessionfinish#pytest.hookspec.pytest_sessionfinish

Solution 2:[2]

I had to tweak @matthewpark319's answer a bit, but adding a session-scoped fixture in conftest.py worked.

import asyncio

import pytest


@pytest.fixture(scope="session")
def event_loop():
    loop = asyncio.get_event_loop()
    yield loop
    loop.close()

If you're using pytest-asyncio, you may also need to edit your pyproject.toml and add:

[tool.pytest.ini_options]
asyncio_mode = "auto"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2