Integration testing FastAPI with user authentication

Question:

I am trying to write some integration tests for my FastAPI endpoints and am not sure what the best solution is to testing the endpoints that require a user to be logged in.

I am following the FastAPI authentication documentation for my auth flow which is just username password and then receiving a token.

How can I test endpoints using a logged in user?

Example endpoint to test:

@app.get("/lists/{id}", response_model=ListDto)
async def get_list(
    id: int,
    current_user: User = Depends(get_current_active_user),
):
    usecase = GetList(list_id=id, current_user=current_user)
    list = usecase()
    if not llist:
        raise HTTPException(status_code=404, detail=f"List with id:{id} not found")
    return list
Asked By: rick_grimes

||

Answers:

To test endpoints that require a user to be logged in, you will need to simulate a login process to obtain a valid token and then pass it as a header to your subsequent requests. Here is an example of how you can do this in your integration tests:

Create a fixture for your client and a test user

from fastapi.testclient import TestClient
from app.main import app

@pytest.fixture(scope="module")
def client():
    with TestClient(app) as c:
      yield c

@pytest.fixture(scope="module")
def test_user():
    return {"username": "testuser", "password": "testpass"}

Write a test case for the login endpoint that retrieves a valid token for your test user.

def test_login(client, test_user):
  response = client.post("/login", data=test_user)
  assert response.status_code == 200
  token = response.json()["access_token"]
  assert token is not None
  return token

Pass the token as a header in subsequent requests that require authentication. For example, here is how you can test the get_list endpoint:

def test_get_list(client, test_user):
  token = test_login(client, test_user)
  response = client.get("/lists/1", headers={"Authorization": f"Bearer {token}"})
  assert response.status_code == 200
  assert response.json()["id"] == 1
Answered By: AKG