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

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