Testing auth¶
How to test authentication in your Bluefox app.
Test setup¶
bluefox-auth uses bluefox-test for its own tests. Your app's tests can follow the same pattern.
conftest.py¶
import pytest
import pytest_asyncio
from bluefox_core.database import BluefoxBase, get_session
from bluefox_test import bluefox_test_setup
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
from bluefox_auth import BluefoxAuth
from bluefox_auth.settings import AuthSettings
# Set up test database with SAVEPOINT isolation
globals().update(
bluefox_test_setup(
base=BluefoxBase,
app_factory=None,
session_dependency=None,
)
)
TEST_SECRET = "test-secret-key-that-is-long-enough-for-validation"
@pytest.fixture
def auth_app(db):
"""FastAPI app with auth configured."""
from types import SimpleNamespace
settings = SimpleNamespace(SECRET_KEY=TEST_SECRET)
app = FastAPI()
# Override the DB session
async def _override_session():
yield db
app.dependency_overrides[get_session] = _override_session
BluefoxAuth(app, settings, cookie_secure=False)
yield app
app.dependency_overrides.clear()
@pytest_asyncio.fixture
async def client(auth_app):
transport = ASGITransport(app=auth_app)
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
yield ac
cookie_secure=False
Set cookie_secure=False in tests — httpx's test transport doesn't use HTTPS.
Testing Bearer auth¶
async def test_protected_route(client):
# Register and login
await client.post(
"/auth/register",
json={"email": "test@example.com", "password": "test-password"},
)
login = await client.post(
"/auth/login",
json={"email": "test@example.com", "password": "test-password"},
)
token = login.json()["access_token"]
# Access protected route
resp = await client.get(
"/your-protected-route",
headers={"Authorization": f"Bearer {token}"},
)
assert resp.status_code == 200
Testing cookie auth¶
async def test_cookie_auth(client):
# Login
login = await client.post(
"/auth/login",
json={"email": "test@example.com", "password": "test-password"},
)
# Set cookies on client
access = login.cookies.get("bf_access_token")
csrf = login.cookies.get("bf_csrf_token")
client.cookies.set("bf_access_token", access)
# GET works without CSRF
resp = await client.get("/your-protected-route")
assert resp.status_code == 200
# POST requires CSRF header
client.cookies.set("bf_csrf_token", csrf)
resp = await client.post(
"/your-protected-route",
headers={"X-CSRF-Token": csrf},
json={"data": "..."},
)
assert resp.status_code == 200
Creating test users directly¶
For tests that don't need to go through the registration flow:
from bluefox_auth.models import BluefoxUser
from bluefox_auth.passwords import hash_password
from bluefox_auth.tokens import create_access_token
from bluefox_auth.settings import AuthSettings
async def test_with_direct_user(db, auth_app, client):
# Create user directly in DB
user = BluefoxUser(
email="test@example.com",
password_hash=hash_password("test-password"),
is_active=True,
)
db.add(user)
await db.flush()
await db.refresh(user)
# Create token directly
settings = auth_app.state.auth_settings
token = create_access_token(user.id, settings)
resp = await client.get(
"/auth/me",
headers={"Authorization": f"Bearer {token}"},
)
assert resp.status_code == 200
Testing with pytest-asyncio¶
bluefox-auth uses asyncio_mode = "auto" in pyproject.toml, so async test functions are automatically detected:
No @pytest.mark.asyncio decorators needed.