Files
Nexus/tests/test_refresh_token_persistence.py
T
2026-07-08 22:31:31 +08:00

74 lines
2.3 KiB
Python

"""Refresh token Redis + MySQL dual persistence."""
from datetime import datetime, timedelta, timezone
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from server.application.services.auth_service import AuthService
from server.domain.models import Admin
@pytest.mark.asyncio
async def test_membership_mysql_fallback_rehydrates_redis():
admin = Admin(id=1, username="admin", password_hash="x", is_active=True, token_version=1)
refresh_repo = AsyncMock()
refresh_repo.exists_valid = AsyncMock(return_value=True)
service = AuthService(
admin_repo=AsyncMock(),
attempt_repo=AsyncMock(),
audit_repo=AsyncMock(),
refresh_token_repo=refresh_repo,
)
service._redis_sadd_refresh = AsyncMock(return_value=True)
with patch("server.infrastructure.redis.client.get_redis") as get_redis:
redis = AsyncMock()
redis.sismember = AsyncMock(return_value=False)
get_redis.return_value = redis
result = await service._refresh_token_membership(1, "secret:1:1")
assert result is True
refresh_repo.exists_valid.assert_awaited_once()
service._redis_sadd_refresh.assert_awaited_once()
@pytest.mark.asyncio
async def test_store_writes_redis_then_mysql():
refresh_repo = AsyncMock()
service = AuthService(
admin_repo=AsyncMock(),
attempt_repo=AsyncMock(),
audit_repo=AsyncMock(),
refresh_token_repo=refresh_repo,
)
service._redis_sadd_refresh = AsyncMock(return_value=True)
await service._store_refresh_token(2, "tok:2:0")
service._redis_sadd_refresh.assert_awaited_once()
refresh_repo.add.assert_awaited_once()
_admin_id, token_hash, expires_at = refresh_repo.add.await_args.args
assert _admin_id == 2
assert len(token_hash) == 64
assert expires_at > datetime.now(timezone.utc)
@pytest.mark.asyncio
async def test_delete_all_clears_both_layers():
refresh_repo = AsyncMock()
service = AuthService(
admin_repo=AsyncMock(),
attempt_repo=AsyncMock(),
audit_repo=AsyncMock(),
refresh_token_repo=refresh_repo,
)
service._redis_delete_all_refresh = AsyncMock()
await service._delete_all_refresh_tokens(3)
service._redis_delete_all_refresh.assert_awaited_once_with(3)
refresh_repo.delete_all_for_admin.assert_awaited_once_with(3)