Comments (9)
I'll just put links here for future strangers.
- https://github.com/florimondmanca/asgi-lifespan#usage (see usage example here)
- https://pypi.org/project/asgi-lifespan/
Also awesome explanation about the async test client: https://fastapi.tiangolo.com/advanced/async-tests/ (it's about FastAPI but it still should be applicable to pure Starlette).
My example of async test client fixture:
# conftest.py
from asgi_lifespan import LifespanManager
from httpx import AsyncClient
@pytest.fixture()
async def client() -> Iterator[AsyncClient]:
async with LifespanManager(app):
async with AsyncClient(app=app, base_url="http://test") as ac:
yield ac
# test_app.py
@pytest.mark.asyncio
async def test_endpoint(client: AsyncClient) -> None:
response = await client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Tomato"}
from starlette.
@mackeyja92 Here's a gist: https://gist.github.com/ryankask/90c0dc155d3f95a52a1eaa0ac4ef63d0.
I needed to make it async all the way down to this call loop.run_until_complete(connection(receive, send))
deep in the adapter so a nested loop wasn't started.
To do this, I combined the ASGI adapter Tom wrote with requests' Session API. I removed some of the Session-related code that I didn't think was relevant but I may have removed or left in too much.
I use pytest with pytest-asyncio doing something like this
@pytest.fixture
def client():
return StarletteTestClient(starlette_app)
@pytest.mark.asyncio
async def test_update_company(client):
company = await CompanyStore.create(name="Great Software")
data = {
"name": "Awesome Software",
}
response = await client.patch(f"/companies/{company.id}", json=data)
assert response.status_code == 200
updated_company = await CompanyStore.get(company.id)
assert updated_company.name == "Awesome Software"
All my app code is async so to test in same way I've always done (arrange, act, assert, this time asynchronously), I think I need an async test client. This way pytest-asyncio can manage the loop and I can use pytest naturally. Maybe I need to just change the way I test so hopefully someone points out a better way.
I thought it would be better to use aiohttp's equivalent of a requests' adapter but I didn't spend much time figuring it out.
from starlette.
For somebody else passing by in search of an AsyncTestClient: async-asgi-testclient made the trick for me.
you can also use httpx and the asgi-lifespan by @florimondmanca !
from starlette.
Okay, so...
The "lifespan" events are useful here. See https://www.starlette.io/events/
One option would be for you to add the setup teardown events to the app when in test mode, and then use with LifespanContext(app)
in the test cases.
Alternatively if you don't want to register the events on the app itself you can use just the lifespan handler by itself, so...
lifespan = LifespanHandler()
# We should probably add a regular function-based interface too. `lifespan.add_event_handler('startup', func)
@lifespan.on_event('startup')
async def startup():
...
@lifespan.on_event('cleanup')
async def cleanup():
...
You're then able to use something like this in your test cases:
with LifetimeContext(lifetime):
...
It's a regular sync interface at that point, but it'll marshall bridging to the async calls for you.
It'd be interesting if we could look at how those would correspond to pytest fixtures.
from starlette.
Also, we may want to reorganise the docs here, so that LifespanContext
gets included in the test section.
from starlette.
Thanks for the tips. I can see how it's possible to use these features along with Starlette's test client.
Since I'm already using pytest-asyncio to test other parts of the app, I'm going to continue using the async test client to keep things consistent.
I'll close this issue since you've answered the original question.
from starlette.
@ryankask Would you be willing to setup a package for your async test client code? I'd love to take a look and see if we could use it as well.
from starlette.
For somebody else passing by in search of an AsyncTestClient: async-asgi-testclient made the trick for me.
from starlette.
For somebody else passing by in search of an AsyncTestClient: async-asgi-testclient made the trick for me.
you can also use httpx and the asgi-lifespan by @florimondmanca !
httpx is much better ! Thx
from starlette.
Related Issues (20)
- Drop `python-multipart` dependency
- Warn users if setting too large of a session object
- Typing error for app.add_exception_handler (Argument "handler" to "add_exception_handler" of "Starlette" has incompatible type) HOT 1
- TrustedHostMiddleware raises RuntimeError on sending response to websocket HOT 2
- typing map _RequestData in testclient.py might be missing type bytes HOT 2
- Enable `branch = true` for `coverage.run` HOT 4
- Fetching API docs occasionally fails at starlette framework middleware issue with streaming large responses
- links on the release-notes not found. HOT 1
- Add `Partitioned` cookie attribute HOT 2
- `RuntimeError("No response returned")` in `BaseHTTPMiddleware` HOT 11
- Incompatibility with anyio v3
- TestClient DeprecationWarning with httpx 0.27.0 HOT 5
- Bug: `_TemplateResponse` is still relying on `request` key from `context` which maybe different from `request` argument to `TemplateResponse`. HOT 4
- How to change the value of request body?
- A `RuntimeError: Stream consumed` error is raised when `request.body()` is read in the custom middleware
- CORSMiddleware always add access-control-allow-credentials regardless of Origin
- ValueError when null byte in URL HOT 2
- responses.py - appears UTF incompatible (Line 58 and probably other places)
- Double path unquote inside _TestClientTransport.__init__ method
- [FeatureRequest] Cant configure request.stream() chunk size -- always 128kb per chunk read HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from starlette.