main.py and then add unit tests that mock the database layer. You can accelerate test scaffolding with GitHub Copilot; always review any generated tests.

Overview
- Goal: Make endpoints and DB access easy to test by isolating business logic.
- Approach: Refactor into a single
app/main.pythat contains:- A Pydantic request model
- A context manager for SQLite connections
- A
fetch_fake_datahelper returning rows as dictionaries - A POST endpoint
/api/v1/getfakedatawith input validation and error handling
- Test strategy: Use
pytest+fastapi.testclient.TestClientand patch DB calls to keep tests fast and deterministic.
- FastAPI docs: https://fastapi.tiangolo.com/
- pytest docs: https://docs.pytest.org/
- SQLite docs: https://www.sqlite.org/docs.html
- GitHub Copilot in Action course: https://learn.kodekloud.com/user/courses/github-copilot-in-action
Original (messy) example
This example illustrates the problem of splitting routing and logic across nested modules — making tests harder to write and maintain.Refactored, testable implementation (app/main.py)
The following is a self-contained FastAPI app that uses SQLite and provides a helper to fetch random rows. It includes validation, explicit errors, and a context manager for DB connections.
{"count": 2} and is available at POST /api/v1/getfakedata.
Before running tests, ensure you have the required test packages installed, for example:
pip install pytest pytest-mock fastapi[all]. The tests below use pytest, unittest.mock.patch, and FastAPI’s TestClient.Test strategy
- Unit tests should avoid hitting a real database — patch
sqlite3.connectorfetch_fake_dataso tests stay fast and deterministic. - Use
fastapi.testclient.TestClientto exercise endpoints. - Keep tests close to the module for small projects (e.g.,
app/test_main.py) or use a top-leveltests/directory for larger projects.
Example pytest file (app/test_main.py)
Place this file next to app/main.py. It demonstrates:
- Mocking the DB connection for
fetch_fake_data - Patching
fetch_fake_datawhen testing the endpoint behavior - Verifying validation and error responses
Test cases matrix
When listing example JSON payloads or code snippets in tables, wrap them in backticks, for example: use
{"count": 2} as the request body.
Run tests
From project root run:- Discover and run tests with pytest:
pytest
Tips and best practices
- Keep business logic (e.g.,
fetch_fake_data) separate from framework glue (FastAPI route handlers) so you can unit test logic without spinning up the full app. - For unit tests: mock external state (DB, network) to keep tests fast and deterministic.
- For integration tests: use a disposable test database and clean up state using fixtures.
- Use
TestClientfor endpoint-level tests and patch the underlying helpers for unit-style tests. - When using GitHub Copilot to scaffold tests: treat outputs as a starting point — verify correctness, edge cases, and error handling.
Avoid running unit tests against your production database. Use mocks for unit tests and a separate ephemeral/test DB for integration tests to prevent data corruption or flaky results.
Wrap up
- Refactoring to a single, well-structured module simplifies testing and reduces coupling between layers.
- Use pytest with FastAPI’s TestClient and mock the database layer to write fast, reliable unit tests.
- Leverage tools like GitHub Copilot to generate test scaffolding quickly, but always review generated code to ensure accurate assertions and coverage.
- FastAPI testing: https://fastapi.tiangolo.com/tutorial/testing/
- pytest: https://docs.pytest.org/
- sqlite: https://www.sqlite.org/docs.html
- GitHub Copilot in Action course: https://learn.kodekloud.com/user/courses/github-copilot-in-action