Skip to main content
ProductsDesktop toolsTASTECADDrawing reviewTASTEFILESFile managementTASTEFTPFile transferTASTESSHRemote workspaceTASTEZIPCompression and extractionDeveloper toolsTASTECODERust integrated development environmentTASTESTUDIOIntegrated development and test environmentTASTEETLData integration (ETL)ServersTASTEREMOTERemote desktop serverTASTEGEOGeospatial serverTASTEMAILMail workspaceGet startedDownloadsDocumentationBuyAll products
Marketplace
News
TechNewsToday's dev newsDeveloper docsProgramming languagesRustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDartWeb front-end frameworksNext.jsReactVue.js · NuxtSvelteKitAngularServer frameworksSpring BootDjangoFastAPIASP.NET CoreNestJS · ExpressApp & desktop frameworksTauriFlutterReact NativeElectronAlgorithmsAlgorithm basicsCore algorithmsAdvanced algorithmsPractical algorithms
CommunityProjectsDevelopment logsPromptsAI tool issuesShowcaseCommunity guide
Work with usTech transferWebsite buildDesktop app buildRelease and payment pipelineSales partnerContact
ServicesRemote desktopCustom installer packages
TASTEDEV
Products

Desktop tools

TASTECADComplex drawings, opened with easeTASTEFILESJust the files you need, as fast as possibleTASTEFTPThe tidiest path for your filesTASTESSHA stronger link between you and your serversTASTEZIPPack faster, unpack safer

Developer tools

TASTECODEEdit, build, debug and test Rust apps in one windowTASTESTUDIOFrom editing to remote tests and approved AI fixesTASTEETLMove data while you watch the values

Servers

TASTEREMOTEA remote desktop you run on your own serverTASTEGEORebuilding a GeoServer-compatible geospatial server in RustTASTEMAILTake back control of your email

Get started

DownloadsLatest builds of every productDocsHow to use each productBuySubscriptions and perpetual licencesAll productsEvery product at a glance
All products
MarketplaceNews
Tech

News

Today's dev newsOfficial announcements on languages, frameworks, GitHub and AIDeveloper docsGuides to languages, frameworks and algorithms

Programming languages

RustTypeScriptJavaScriptPythonGoC#JavaCC++KotlinDart

Frameworks

Web front-end frameworksNext.jsReactVue.js · NuxtSvelteKitAngular
Server frameworksSpring BootDjangoFastAPIASP.NET CoreNestJS · Express
App & desktop frameworksTauriFlutterReact NativeElectron

Algorithms

Algorithm basicsComplexity analysis · Sorting · Searching · Basic data structures · Trees and heapsCore algorithmsGraph traversal · Shortest paths & minimum spanning trees · Dynamic programming · Greedy algorithms · Divide and conquer · BacktrackingAdvanced algorithmsString algorithms · Math and number theory · Bit manipulation · Segment trees · Union-findPractical algorithmsCoding interview strategy · LRU cache · Rate limiting · Consistent hashing
All development docs
Community
ProjectsDiscover builders and their workDevelopment logsDecisions and lessons learnedPromptsReusable instructionsAI tool issuesProblems and workarounds for Claude, Codex, GeminiShowcaseFinished resultsCommunity guideHow we build in the open
Work with us
Tech transferNative apps in Rust and eguiWebsite build10 languages, accounts, docs and downloadsDesktop app buildRust and egui, no WebViewRelease and payment pipelineSigning, MSI, deb, rpm, AppImage, hashesSales partnerRecommend us and earn 30%ContactBuilds, partnerships and investment
Services
Remote desktopReach your computer from a browserCustom installer packagesOnly the features you need, settings preloaded
Buy
EN
한국어EnglishDeutschEspañolFrançaisItalianoPortuguês (Brasil)日本語简体中文繁體中文
Log in
Log in
TASTEDEV

From small tools to better development.

support@tastedev.netSupport TASTEDEV
ProductsProduct lineupBuyDocsDownloadsMarketplaceSupport
CommunityProjectsDevelopment logsPromptsAI tool issuesShowcase
PoliciesPrivacy policyTerms of serviceSubscription termsRefund policyCommunity guidelines
AccountLog inSign up
Visitors
Today
012345678901234567890123456789012345678901234567890123456789
Yesterday
012345678901234567890123456789012345678901234567890123456789
Total views
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
Company
GXSOFT
Representative
CHOI YOUNG GU
Business registration number
853-44-00368
Address
9F V24, 351 Gyeongin-ro, Michuhol-gu, Incheon, Republic of Korea
Phone
+82-10-4404-1523
Email
whitecalvin@tastedev.net
Privacy officer
CHOI YOUNG GU

© 2026 TASTEDEVProduct information is based on verified development sources.Released · improving

FastAPI docs
FastAPI
Getting Started with FastAPIProject StructureCore ConceptsData and StateTestingDeployment
Discussions

FastAPI guide · 5/6

Testing

You can test a FastAPI application without starting a server. This chapter covers testing endpoints with TestClient and pytest, swapping databases and settings for test versions with dependency overrides, async tests, and measuring coverage.

Setup

TestClient is built on HTTPX. If you installed fastapi[standard], HTTPX is already there, so you only need pytest:

pip install pytest

Put tests in files named tests/test_*.py and start test function names with test_. Running pytest from the project root discovers and runs them. To make the app package importable, either add an empty __init__.py to tests or set pythonpath = ["."] in the pytest section of pyproject.toml.

A first test with TestClient

Hand your app to TestClient and you can send requests and inspect responses much as you would with requests. Test functions are plain def.

# tests/test_main.py
from fastapi.testclient import TestClient

from app.main import app

client = TestClient(app)


def test_read_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello, world!"}


def test_read_item_validation_error():
    response = client.get("/items/not-a-number")
    assert response.status_code == 422


def test_create_item():
    response = client.post("/items", json={"name": "Pen", "price": 1.5})
    assert response.status_code == 201
    assert response.json()["name"] == "Pen"

Pass headers with headers={"X-Token": "..."} and query parameters with params={"q": "pen"}. Tests asserting that bad input returns 422 are worth having too: they catch accidental changes to your API contract early.

Overriding dependencies

To replace a real database or external service with a test implementation, map the original dependency to a substitute in app.dependency_overrides. This example swaps the session dependency for an in-memory SQLite database:

# tests/test_heroes.py
import pytest
from fastapi.testclient import TestClient
from sqlmodel import Session, SQLModel, create_engine
from sqlmodel.pool import StaticPool

from app.db import get_session
from app.main import app


@pytest.fixture(name="session")
def session_fixture():
    engine = create_engine(
        "sqlite://",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    SQLModel.metadata.create_all(engine)
    with Session(engine) as session:
        yield session


@pytest.fixture(name="client")
def client_fixture(session: Session):
    app.dependency_overrides[get_session] = lambda: session
    client = TestClient(app)
    yield client
    app.dependency_overrides.clear()


def test_create_hero(client: TestClient):
    response = client.post(
        "/heroes", json={"name": "Deadpond", "secret_name": "Dive Wilson"}
    )
    data = response.json()
    assert response.status_code == 200
    assert data["name"] == "Deadpond"
    assert "secret_name" not in data

StaticPool keeps a single connection so the in-memory database does not vanish between connections. Calling dependency_overrides.clear() after each test restores the real dependencies so tests do not leak into each other. The get_settings dependency can be overridden the same way.

Testing apps with a lifespan

Use TestClient in a with block and the app's lifespan startup and shutdown code runs around your test. Do this whenever the app loads models or opens connections at startup.

from fastapi.testclient import TestClient

from app.main import app


def test_with_lifespan():
    with TestClient(app) as client:
        response = client.get("/health")
        assert response.status_code == 200

Async tests

When a test also needs to await something, such as an async database call, use HTTPX's AsyncClient with ASGITransport. AnyIO's pytest plugin can run the test function asynchronously.

import pytest
from httpx import ASGITransport, AsyncClient

from app.main import app


@pytest.mark.anyio
async def test_root_async():
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as ac:
        response = await ac.get("/")
    assert response.status_code == 200

Running tests and coverage

pytest                         # run everything
pytest tests/test_heroes.py -v # one file, verbose
pytest -k create               # only tests with "create" in the name
pip install pytest-cov
pytest --cov=app               # measure coverage

Summary

  • TestClient(app) sends requests without a server so you can assert on status codes and JSON.
  • app.dependency_overrides swaps databases, settings or authentication for test versions.
  • Use with TestClient(app) as client: when the app relies on lifespan.
  • For async code inside tests, use HTTPX AsyncClient with ASGITransport.
Questions about this chapter?
Previous chapterData and StateNext chapterDeployment

0 comments

Top commentsNewest first

Sign in · Sign in to leave a comment.