Files
life-echo/api/tests/test_auth_flow_http.py

101 lines
3.3 KiB
Python
Raw Normal View History

"""Auth HTTP 契约:注册 / 登录 / 刷新 / 受保护 /me依赖注入 mock"""
from __future__ import annotations
from unittest.mock import AsyncMock, MagicMock
import pytest
from fastapi import FastAPI
from httpx import ASGITransport, AsyncClient
from app.core.dependencies import get_current_user
from app.features.auth.deps import get_auth_service
from app.features.auth.router import router as auth_router
from app.features.auth.service import AuthService
@pytest.fixture
def auth_app(make_test_user) -> FastAPI:
app = FastAPI()
app.include_router(auth_router)
mock_service = MagicMock(spec=AuthService)
mock_service.register = AsyncMock(
return_value={"access_token": "access-reg", "refresh_token": "refresh-reg"}
)
mock_service.login = AsyncMock(
return_value={"access_token": "access-login", "refresh_token": "refresh-login"}
)
mock_service.refresh_tokens = AsyncMock(
return_value={"access_token": "access-new", "refresh_token": "refresh-new"}
)
app.dependency_overrides[get_auth_service] = lambda: mock_service
app.dependency_overrides[get_current_user] = lambda: make_test_user()
app.state._mock_auth_service = mock_service
return app
@pytest.mark.asyncio
async def test_register_login_refresh_me(auth_app: FastAPI, unique_phone: str) -> None:
transport = ASGITransport(app=auth_app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
reg = await ac.post(
"/api/auth/register",
json={
"phone": unique_phone,
"password": "secret12",
"nickname": "T",
"agreed_to_terms": True,
},
)
assert reg.status_code == 201
body = reg.json()
assert body["access_token"] == "access-reg"
login = await ac.post(
"/api/auth/login",
json={
"phone": unique_phone,
"password": "secret12",
"agreed_to_terms": True,
},
)
assert login.status_code == 200
assert login.json()["access_token"] == "access-login"
ref = await ac.post(
"/api/auth/refresh",
json={"refresh_token": "refresh-login"},
)
assert ref.status_code == 200
assert ref.json()["access_token"] == "access-new"
me = await ac.get(
"/api/auth/me",
headers={"Authorization": "Bearer any"},
)
assert me.status_code == 200
assert me.json()["nickname"] == "测试用户"
svc: MagicMock = auth_app.state._mock_auth_service
svc.register.assert_awaited_once()
svc.login.assert_awaited_once()
svc.refresh_tokens.assert_awaited_once_with(refresh_token="refresh-login")
@pytest.mark.asyncio
async def test_me_without_auth_returns_401() -> None:
app = FastAPI()
app.include_router(auth_router)
mock_service = MagicMock(spec=AuthService)
app.dependency_overrides[get_auth_service] = lambda: mock_service
# 不覆盖 get_current_user — 使用真实 OAuth2无 header 时应 401
transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as ac:
r = await ac.get("/api/auth/me")
assert r.status_code == 401