{"id":4269,"library":"starlette-testclient","title":"Starlette TestClient","description":"starlette-testclient is a backport of Starlette's TestClient that utilizes the `requests` library instead of `httpx`. Its primary goal is to offer a familiar synchronous testing interface for ASGI applications, easing the migration for users accustomed to `requests`-based testing. The current version is 0.4.1. Releases are infrequent, with the latest significant update in April 2024, reflecting a maintenance cadence focused on compatibility rather than rapid feature development, as its purpose is to bridge the gap for users transitioning from older Starlette testing practices.","status":"maintenance","version":"0.4.1","language":"python","source_language":"en","source_url":"https://github.com/Kludex/starlette-testclient","tags":["testing","starlette","fastapi","http","requests","backport"],"install":[{"cmd":"pip install starlette-testclient","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"This library explicitly uses 'requests' as its underlying HTTP client for testing, distinguishing it from modern Starlette's 'httpx'-based TestClient.","package":"requests","optional":false},{"reason":"It is a backport of Starlette's TestClient and is designed to test Starlette (and FastAPI) applications.","package":"starlette","optional":false},{"reason":"Starlette itself is built on 'anyio', and starlette-testclient v0.4.0 added explicit compatibility for 'anyio<3' and 'anyio>=4'.","package":"anyio","optional":false}],"imports":[{"note":"While 'starlette.testclient.TestClient' is valid, it uses 'httpx' and has an asynchronous interface. This library specifically provides a 'requests'-based, synchronous client, which users might mistakenly assume is available via the 'starlette' package itself after framework updates.","wrong":"from starlette.testclient import TestClient","symbol":"TestClient","correct":"from starlette_testclient import TestClient"}],"quickstart":{"code":"from starlette.applications import Starlette\nfrom starlette.responses import PlainTextResponse\nfrom starlette.routing import Route\nfrom starlette_testclient import TestClient\n\nasync def homepage(request):\n    return PlainTextResponse(\"Hello, world!\")\n\nroutes = [\n    Route(\"/\", endpoint=homepage),\n]\n\napp = Starlette(routes=routes)\n\ndef test_homepage_sync():\n    client = TestClient(app)\n    response = client.get(\"/\")\n    assert response.status_code == 200\n    assert response.text == \"Hello, world!\"\n\ntest_homepage_sync()\nprint(\"Quickstart test passed!\")","lang":"python","description":"This example demonstrates how to create a basic Starlette application and then test it using `starlette-testclient`'s synchronous `TestClient`."},"warnings":[{"fix":"Ensure your `anyio` dependency is pinned to `<3` or `>=4`. If using an older `starlette-testclient` version, update to 0.4.0+.","message":"Version 0.4.0 of `starlette-testclient` added explicit support for `anyio<3` and `anyio>=4`. Using `anyio` versions between 3.0 and 3.x (exclusive of <3) may lead to unexpected compatibility issues or errors due to changes in `anyio`'s API, specifically around `start_blocking_portal`.","severity":"gotcha","affected_versions":"<0.4.0 and potentially v0.4.0+ with specific 'anyio' 3.x versions"},{"fix":"Avoid accessing async resources created within the ASGI app's lifecycle directly from `async def` test functions. If async test logic is necessary, use `httpx.AsyncClient` with `ASGITransport` instead, or ensure resources are managed within the same event loop context.","message":"Starlette's `TestClient` (and this backport) executes the ASGI application in a separate background thread, providing a synchronous testing interface for an asynchronous application. This can cause problems when attempting to access asynchronous resources (e.g., database connections, `httpx.AsyncClient` instances) that were initialized within the application's startup events from an `async` test function running in the main thread's event loop.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure cookie `max_age` values are integers. Verify that the `TestClient`'s `base_url` aligns with the domain for which cookies are being set, particularly for explicit domain settings.","message":"When using `TestClient`, issues with cookies not being set or retrieved correctly have been reported. This can sometimes be traced to `max_age` cookie parameters being floats instead of integers, or inconsistencies between the `base_url` used in the client and the cookie's domain.","severity":"gotcha","affected_versions":"All versions"},{"fix":"As a workaround, you can initialize `TestClient` with `TestClient(app, backend_options={'loop_factory': asyncio.new_event_loop})` or, if using PyCharm, disable `python.debug.asyncio.repl` in `Help | Find Actions | Registry`.","message":"Debugging tests with `starlette-testclient` in PyCharm (or other IDEs that patch `asyncio` APIs) can lead to `AttributeError` (e.g., `'_UnixSelectorEventLoop' object has no attribute '_compute_internal_coro'`). This occurs because PyCharm's patched `asyncio.new_event_loop()` clashes with `anyio`'s event loop detection.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'0.4.1':49 '2024':60 'accustom':40 'applic':34 'april':59 'asgi':33 'backport':8,94 'base':43 'bridg':78 'cadenc':64 'compat':67 'current':46 'develop':72 'eas':35 'familiar':28 'fastapi':91 'featur':71 'focus':65 'gap':80 'goal':23 'http':92 'httpx':20 'infrequ':52 'instead':18 'interfac':31 'latest':55 'librari':17 'mainten':63 'migrat':37 'offer':26 'older':85 'practic':88 'primari':22 'purpos':75 'rapid':70 'rather':68 'reflect':61 'releas':50 'request':16,42,93 'signific':56 'starlett':1,4,10,86,90 'starlette-testcli':3 'synchron':29 'test':30,44,87,89 'testclient':2,5,12 'transit':83 'updat':57 'user':39,82 'util':14 'version':47","created_at":"2026-04-12T03:48:09.359566+00:00","updated_at":"2026-04-16T22:21:45.313137+00:00","problems":[{"fix":"Install the package using `pip install starlette-testclient` and ensure the import is `from starlette_testclient import TestClient`.","cause":"The `starlette-testclient` package is not installed in the current Python environment or there is a typo in the import statement.","error":"ModuleNotFoundError: No module named 'starlette_testclient'"},{"fix":"Ensure you are passing a properly initialized ASGI application instance (e.g., `Starlette()`, `FastAPI()`) to `TestClient`.","cause":"The object passed to the `TestClient` constructor is not a valid ASGI application (a callable accepting `scope`, `receive`, `send`).","error":"TypeError: 'X' object is not callable"},{"fix":"`starlette-testclient` is synchronous and does not require `async with` context management or an `aclose()` call; tests are run synchronously.","cause":"`starlette-testclient` uses the synchronous `requests` library and does not have an `aclose` method, which is typically found in `httpx`-based clients for asynchronous resource management.","error":"AttributeError: 'TestClient' object has no attribute 'aclose'"},{"fix":"To use the `requests`-based backport, change the import statement to `from starlette_testclient import TestClient`.","cause":"The user intends to use the `requests`-based `starlette-testclient` but is importing the `TestClient` from the standard `starlette` library, which uses `httpx` and may have different behaviors.","error":"from starlette.testclient import TestClient"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.4.1","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/sponsors/Kludex","docs":null,"changelog":null,"pypi":"https://pypi.org/project/starlette-testclient/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["testing","web-framework"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-08-29","next_check":"2026-07-28","install_tag":null}}