Search code examples
pythontestingintegration-testingfastapi

Integration testing FastAPI with user authentication


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

Solution

  • 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