102 lines
3.7 KiB
Python
102 lines
3.7 KiB
Python
"""Mock 短信登录路由:配置门禁与返回的 JWT 可解析性。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
from fastapi import FastAPI
|
|
from httpx import ASGITransport, AsyncClient
|
|
|
|
from app.core.config import settings
|
|
from app.core.security import create_access_token, verify_token
|
|
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 mock_sms_app() -> FastAPI:
|
|
app = FastAPI()
|
|
app.include_router(auth_router)
|
|
mock_service = MagicMock(spec=AuthService)
|
|
uid = str(uuid.uuid4())
|
|
mock_service.mock_sms_login = AsyncMock(
|
|
return_value={
|
|
"access_token": create_access_token(data={"sub": uid}),
|
|
"refresh_token": "rt-mock",
|
|
}
|
|
)
|
|
app.dependency_overrides[get_auth_service] = lambda: mock_service
|
|
app.state._mock_service = mock_service
|
|
app.state._mock_uid = uid
|
|
return app
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mock_sms_login_disabled_returns_404(mock_sms_app, monkeypatch) -> None:
|
|
monkeypatch.setattr(settings, "mock_sms_login_enabled", False)
|
|
monkeypatch.setattr(settings, "app_environment", "development")
|
|
transport = ASGITransport(app=mock_sms_app)
|
|
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
|
r = await ac.post(
|
|
"/api/auth/mock/sms-login",
|
|
json={"phone": "13800138000", "agreed_to_terms": True},
|
|
)
|
|
assert r.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mock_sms_login_production_returns_404(mock_sms_app, monkeypatch) -> None:
|
|
monkeypatch.setattr(settings, "mock_sms_login_enabled", True)
|
|
monkeypatch.setattr(settings, "app_environment", "production")
|
|
transport = ASGITransport(app=mock_sms_app)
|
|
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
|
r = await ac.post(
|
|
"/api/auth/mock/sms-login",
|
|
json={"phone": "13800138000", "agreed_to_terms": True},
|
|
)
|
|
assert r.status_code == 404
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mock_sms_login_enabled_returns_valid_access_jwt(
|
|
mock_sms_app, monkeypatch
|
|
) -> None:
|
|
monkeypatch.setattr(settings, "mock_sms_login_enabled", True)
|
|
monkeypatch.setattr(settings, "app_environment", "development")
|
|
transport = ASGITransport(app=mock_sms_app)
|
|
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
|
r = await ac.post(
|
|
"/api/auth/mock/sms-login",
|
|
json={"phone": "13800138000", "agreed_to_terms": True},
|
|
)
|
|
assert r.status_code == 200
|
|
body = r.json()
|
|
assert body.get("token_type") == "bearer"
|
|
access = body["access_token"]
|
|
payload = verify_token(access)
|
|
assert payload is not None
|
|
assert payload.get("type") == "access"
|
|
assert payload.get("sub") == mock_sms_app.state._mock_uid
|
|
|
|
svc: MagicMock = mock_sms_app.state._mock_service
|
|
svc.mock_sms_login.assert_awaited_once_with(
|
|
phone="13800138000",
|
|
nickname=None,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_mock_sms_login_requires_terms(mock_sms_app, monkeypatch) -> None:
|
|
monkeypatch.setattr(settings, "mock_sms_login_enabled", True)
|
|
monkeypatch.setattr(settings, "app_environment", "development")
|
|
transport = ASGITransport(app=mock_sms_app)
|
|
async with AsyncClient(transport=transport, base_url="http://test") as ac:
|
|
r = await ac.post(
|
|
"/api/auth/mock/sms-login",
|
|
json={"phone": "13800138000", "agreed_to_terms": False},
|
|
)
|
|
assert r.status_code == 400
|