Should I test that?

Should I test API endpoints?

Verdict

Yes

Give each API endpoint one HTTP-level test that sends a request and checks the status code and the response fields the client reads; leave edge cases to the tests of the service code behind the endpoint.

Why

Test API endpoints minimally: one test per endpoint that sends an HTTP request and checks the status code and the fields the client reads. The typical case is a JSON endpoint that your own app calls, behind an authentication layer applied to every route, with the logic in a service that has its own tests. Blast radius is users and Change frequency is regularly, because a broken endpoint breaks an app screen and endpoints gain fields with most features. Detectability is same-day and Reversibility is with-effort, because error alerts show a 500 within hours, and a write endpoint that binds a field wrongly saves records that need repair. Test cost is moderate, because each test runs the web layer and a test database, so rule R12 gives Test minimally.

When the decision changes
WhenDecisionWhy
The endpoint returns or changes records that only a logged-in user, or only the record's owner, may seeTest mandatory, including a request without credentials and a request for another user's record, both of which must failBlast radius rises to safety-or-legal and Detectability to never, because a missing access check returns the data without an error
The endpoint charges a card or issues a refundTest mandatory: the main path, every known failure and the boundary amountsBlast radius rises to money and Reversibility to costly
The endpoint takes two parameters of one type, such as from and to dates for an order searchTest: send distinct values and assert that the response holds only records between themDetectability moves to eventually, because swapped dates return a plausible result of the right type
The endpoint is a health check that the load balancer calls before it sends traffic to a new releaseDo not test the health check; the load balancer checks it on every deployDetectability drops to immediately and Reversibility to trivial, because a failed check stops the deploy and the old release keeps serving
A test of the endpoint needs a search cluster and a message broker that CI does not haveDo not add an endpoint test; watch the endpoint's error rate after each deployTest cost rises to heavy while Detectability stays same-day
Partner services that you cannot make update read the endpoint's responsesTest minimally: one test per endpoint that asserts the field names partners readChange frequency falls to rarely and Detectability moves to eventually, which keeps the decision at Test minimally

What breaks if you don't test

An endpoint breaks between the HTTP request and the service call, where service tests do not look. A renamed route, a request field that no longer binds, or a serializer setting changed for another feature passes every service test. The app gets a 404, a 422 or a response without the field it reads, and alerts or support tickets report it the same day.

What you lose if you over-test

The common over-test gives every endpoint a test per validation rule, status code and optional field. At ten tests per endpoint, a 40-endpoint API carries 400 HTTP tests that each run the request pipeline and a database. A change to the shared error format then breaks every test that asserts on an error body, although no client broke.

How to test

Write one test per endpoint with the framework's test client: TestClient in FastAPI or MockMvc in Spring. Send the request the app sends and assert the status code and the body fields it reads; for a write endpoint, read the record back. Most endpoints return data that belongs to someone, so add one test that sends an anonymous request to every route, and ownership tests from OWASP API1:2023. Leave error branches to the service tests until a bug in one reaches a client.

When the answer changes

  • The endpoint checks access itself instead of relying on a layer applied to every route.
  • The endpoint moves money.
  • Clients you cannot update, such as partner services, read its responses.

Real incident + Code example

The export that skipped the login

On a FastAPI backend for a B2B ordering app I worked on, every router was included with dependencies=[Depends(require_user)], a router-level dependency that rejects requests without a valid token. A developer added a reports router for a CSV export and included it without that argument. Its test passed, because the shared client fixture sent a token that the endpoint never checked. For nine days, GET /api/reports/orders.csv returned every customer's orders to anyone with the URL, until a scheduled penetration test requested it without a token. We added one test that sends an anonymous request to every registered route:

import re

import pytest
from fastapi.routing import APIRoute
from fastapi.testclient import TestClient

from app.main import app

PUBLIC = {("GET", "/health"), ("POST", "/api/login")}

ROUTES = sorted(
    (method, re.sub(r"\{[^}]+\}", "1", route.path))
    for route in app.routes
    if isinstance(route, APIRoute)
    for method in route.methods
    if (method, route.path) not in PUBLIC
)


@pytest.mark.parametrize("method,path", ROUTES)
def test_route_rejects_anonymous_request(method, path):
    response = TestClient(app).request(method, path)
    assert response.status_code == 401

A new endpoint joins the list when it is registered, so nobody has to remember its access test.

FAQ

Should I test every endpoint?

Yes, give every endpoint one HTTP-level test of its main path, plus one shared test that sends an anonymous request to every route. Add more tests only to endpoints that move money, check who owns a record, or take several parameters of one type.

Should I unit test a web service?

No, test a web service's endpoints through HTTP requests, and unit test the logic behind them in service classes. A unit test that calls an endpoint method directly skips routing, authentication and serialization, where endpoints break.

Should API tests check authentication on every endpoint?

Yes, every endpoint that requires a login needs a test that sends a request without credentials and expects 401. One parametrized test that reads the framework's route table covers every endpoint, including endpoints added later.