14

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.

Mathieson
  • 1,698
  • 2
  • 17
  • 19

2 Answers2

12

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():
    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        loop = asyncio.new_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"
RobinFrcd
  • 4,439
  • 4
  • 25
  • 49
8

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

matthewpark319
  • 1,214
  • 1
  • 14
  • 16