0

Please help me. How to fix it? The error appears only when using cookies in test_logout()

conftest.py
...............

@pytest_asyncio.fixture(autouse=True, scope='session')
async def prepare_database():
    async with engine_test.begin() as conn:
        await conn.run_sync(metadata.create_all)
    yield
    async with engine_test.begin() as conn:
        await conn.run_sync(metadata.drop_all)


@pytest.fixture(scope='session')
def event_loop(request):
    loop = asyncio.get_event_loop_policy().new_event_loop()
    yield loop
    loop.close()


client = TestClient(app)

...............

test_auth.py
import asyncio
import pytest
import pytest_asyncio

from conftest import client


def test_register():
    response = client.post("/auth/register", json={
        "email": "[email protected]",
        "password": "string",
        "is_active": True,
        "is_superuser": False,
        "is_verified": False
    })
    assert response.status_code == 201


def test_login():
    data = {
        "username": "[email protected]",
        "password": "string",
    }
    encoded_data = "&".join([f"{key}={value}" for key, value in data.items()])
    headers = {
        "Content-Type": "application/x-www-form-urlencoded"
    }
    response = client.post("/auth/login", data=encoded_data, headers=headers)
    assert response.status_code == 204


def test_logout():
    cookies = {k: client.cookies.get(k) for k in client.cookies}
    print(cookies)
    headers = {
        "Content-Type": "application/json"
    }
    response = client.post("/auth/logout", headers=headers, cookies=cookies)
    print(response)
    assert response.status_code == 201


Pytest:

platform linux -- Python 3.11.3, pytest-7.4.0, pluggy-1.2.0 -- /home/djamal/PycharmProjects/green/venv/bin/python cachedir: .pytest_cache rootdir: /home/djamal/PycharmProjects/green/server plugins: anyio-3.7.1, asyncio-0.21.0 asyncio: mode=Mode.STRICT collected 3 items

tests/test_auth.py::test_register PASSED [ 33%] tests/test_auth.py::test_login PASSED [ 66%] tests/test_auth.py::test_logout FAILED [100%]

FAILURES ======================================================================================== test_logout ______________________________________________________________________________________

self = Connection<host=localhost,port=6379,db=0>, disable_decoding = False, timeout = None

async def read_response( self, disable_decoding: bool = False, timeout: Optional[float] = None, *, disconnect_on_error: bool = True, ): """Read the response from a previously sent command""" read_timeout = timeout if timeout is not None else self.socket_timeout host_error = self._host_error() try: if read_timeout is not None: async with async_timeout(read_timeout): response = await self._parser.read_response( disable_decoding=disable_decoding ) else: response = await self._parser.read_response( disable_decoding=disable_decoding )

../venv/lib/python3.11/site-packages/redis/asyncio/connection.py:782: _ ../venv/lib/python3.11/site-packages/redis/asyncio/connection.py:262: in read_response response = await self._read_response(disable_decoding=disable_decoding) ../venv/lib/python3.11/site-packages/redis/asyncio/connection.py:270: in _read_response raw = await self._readline() ../venv/lib/python3.11/site-packages/redis/asyncio/connection.py:344: in _readline data = await self._stream.readline() /usr/lib/python3.11/asyncio/streams.py:545: in readline line = await self.readuntil(sep) /usr/lib/python3.11/asyncio/streams.py:637: in readuntil await self._wait_for_data('readuntil') _

self = <StreamReader transport=<_SelectorSocketTransport closing fd=18>>, func_name = 'readuntil'

async def _wait_for_data(self, func_name): """Wait until feed_data() or feed_eof() is called.

If stream was paused, automatically resume it. """ StreamReader uses a future to link the protocol feed_data() method to a read coroutine. Running two read coroutines at the same time would have an unexpected behaviour. It would not possible to know which coroutine would get the next data. if self._waiter is not None: raise RuntimeError( f'{func_name}() called while another coroutine is ' f'already waiting for incoming data')

assert not self._eof, '_wait_for_data after EOF'

Waiting for data while paused will make deadlock, so prevent it. This is essential for readexactly(n) for case when n > self._limit. if self._paused: self._paused = False self._transport.resume_reading()

self._waiter = self._loop.create_future() try: await self._waiter E RuntimeError: Task <Task pending name='anyio.from_thread.BlockingPortal._call_func' coro=<BlockingPortal._call_func() running at /home/djamal/PycharmProjects/green/venv/lib/python3.11/site-packages/anyio/from_thread.py:217> cb=[TaskGroup._spawn..task_done() at /home/djamal/PycharmProjects/green/venv/lib/python3.11/site-packages/anyio/_backends/_asyncio.py:661]> got Future attached to a different loop

/usr/lib/python3.11/asyncio/streams.py:522: RuntimeError

During handling of the above exception, another exception occurred:

def test_logout(): cookies = {k: client.cookies.get(k) for k in client.cookies} print(cookies) headers = { "Content-Type": "application/json" } response = client.post("/auth/logout", headers=headers, cookies=cookies)

tests/test_auth.py:38: _ .......................... _

self = <_UnixSelectorEventLoop running=False closed=True debug=False>

def _check_closed(self): if self._closed: raise RuntimeError('Event loop is closed') E RuntimeError: Event loop is closed

/usr/lib/python3.11/asyncio/base_events.py:519: RuntimeError Captured stdout call ---------------------------------------------------------------------------------- {'fastapiusersauth': 'X5LEEnDGUSGXIhA5gOTQJSyJQ0g7xsKXvx4v2xBFCv8'} short test summary info ================================================================================ FAILED tests/test_auth.py::test_logout - RuntimeError: Event loop is closed 1 failed, 2 passed in 1.00s ==============================================================================

I've been busy with this for 4 hours, ai gpt didn't help

1 Answer 1

1

You should create your client in a fixture, and set the scope to "module" or "session" to reuse it across tests.

https://tonybaloney.github.io/posts/async-test-patterns-for-pytest-and-unittest.html

@pytest_asyncio.fixture(scope="session", autouse=False)
async def async_client():
    async with AsyncClient(app=app, base_url='http://test') as client:
        yield client
    await client.close()

@pytest.mark.asyncio
async def test_login(async_client):
    await async_client.post(...)

@pytest.mark.asyncio
async def test_logout(async_client):
    await async_client.post(...)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.