Open slavict opened 1 year ago
Maybe that I did't understand how to use 'ReusableClient' class in right way, If that , I will be very grateful to see more complex example in documentation or at least in tests.
Maybe that I did't understand how to use 'ReusableClient' class in right way, If that , I will be very grateful to see more complex example in documentation or at least in tests.
I'll post an example here and then to the docs later today.
Any update on this? I am writing tests for setting cookies, the default app.test_client
doesn't work.
I try to monkey-patch the application, replacing app.test_client
with ReusableTestClient
, and got AttributeError: Setting variables on Sanic instances is not allowed. You s...
. I know how to circumvent that as I have 2 decades of python experience (with dunder methods trick), but I don't think it's the correct way...
It worked before (sanic<=20.x.x, IIRC), basically it allows me to pass in cookies=cookies
to simulate user session. see:
https://github.com/pyx/sanic-cookiesession/blob/9ea4491e1ba63496d8fd6dd9e18deb9aa22a8fb0/tests/test_session.py#L38
I was able to create a ReusableTestClient
fixture. My environment is sanic==23.12.1
and python3.12
.
Here is how I I did this
# conftest.py
from my_app import create_app
@pytest.fixture
def config():
return {'DEBUG': True}
@pytest.fixture
def app(config):
Sanic.test_mode = True
return create_app(config)
@pytest.fixture
def test_cli(app, event_loop):
with ReusableClient(app, loop=event_loop) as cli:
try:
yield cli
finally:
event_loop.run_until_complete(cli._session.aclose()) # close request
where event_loop
is the default loop from pytest-asyncio
.
There is one issue with the ReusableClient
. It doesn't close the connection correctly. First it closes the server socket and only then closes the HTTP client session. This creates a deadlock as server waits for all client connections to be closed. As you can see I added a workaround solution for this.
Here is a sample how this fixture can be used
# test_auth.py
def test_auth_token_missing(test_cli):
req, resp = test_cli.get('/api/v1/sample.png')
assert resp.status == 401
assert resp.json == {
'details': 'Authentication credentials were not provided'
}
You can also create test client with predefined headers
@pytest.fixture
def auth_cli(app, token, event_loop):
with ReusableClient(
app,
loop=event_loop,
client_kwargs={'headers': {'Authorization': f'Bearer {token}'}}
) as cli:
try:
yield cli
finally:
event_loop.run_until_complete(cli._session.aclose()) # close request
If you need to run something async you can use event_loop.run_until_complete
wrapper for this
def test_reader_cache(app, event_loop, auth_cli):
req, resp = auth_cli.get('/api/v1/sample.png')
assert resp.status == 200
assert len(app.ctx.reader.cache) == 1
event_loop.run_until_complete(asyncio.sleep(0.4)) # make sure cleanup task has been called
assert len(app.ctx.reader.cache) == 0
How to reproduce
Error that I got