完成渠道模块的单元测试目录搭建,新增多个领域模型、端口、中间件、事件、服务以及基础设施层的单元测试文件,同时补充了conftest.py的环境变量配置,完善测试基础环境。
99 lines
4.0 KiB
Python
99 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
|
|
from yuxi.channel.application.service.auth_service import AuthService
|
|
|
|
|
|
class TestAuthService:
|
|
@pytest.fixture
|
|
def mock_rate_limiter(self):
|
|
return AsyncMock()
|
|
|
|
@pytest.fixture
|
|
def auth_service(self, mock_rate_limiter):
|
|
return AuthService(
|
|
mock_rate_limiter,
|
|
token="test_token",
|
|
password="test_password",
|
|
max_attempts=3,
|
|
lockout_seconds=300,
|
|
)
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_no_credentials_configured(self, mock_rate_limiter):
|
|
service = AuthService(mock_rate_limiter)
|
|
passed, reason = await service.authenticate("")
|
|
assert passed is True
|
|
assert reason == ""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_with_valid_bearer_token(self, auth_service, mock_rate_limiter):
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
passed, reason = await auth_service.authenticate("Bearer test_token")
|
|
assert passed is True
|
|
assert reason == ""
|
|
mock_rate_limiter.reset.assert_awaited_once()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_with_invalid_bearer_token(self, auth_service, mock_rate_limiter):
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
mock_rate_limiter.check_and_incr.return_value = True
|
|
passed, reason = await auth_service.authenticate("Bearer wrong_token")
|
|
assert passed is False
|
|
assert reason == "auth failed"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_with_valid_basic_password(self, auth_service, mock_rate_limiter):
|
|
import base64
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
credentials = base64.b64encode(b"user:test_password").decode()
|
|
passed, reason = await auth_service.authenticate(f"Basic {credentials}")
|
|
assert passed is True
|
|
assert reason == ""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_with_invalid_basic_password(self, auth_service, mock_rate_limiter):
|
|
import base64
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
mock_rate_limiter.check_and_incr.return_value = True
|
|
credentials = base64.b64encode(b"user:wrong_password").decode()
|
|
passed, reason = await auth_service.authenticate(f"Basic {credentials}")
|
|
assert passed is False
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_when_locked(self, auth_service, mock_rate_limiter):
|
|
mock_rate_limiter.is_locked.return_value = (True, 120)
|
|
passed, reason = await auth_service.authenticate("Bearer test_token")
|
|
assert passed is False
|
|
assert "retry after" in reason
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_rate_limited(self, auth_service, mock_rate_limiter):
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
mock_rate_limiter.check_and_incr.return_value = False
|
|
passed, reason = await auth_service.authenticate("Bearer wrong_token")
|
|
assert passed is False
|
|
assert reason == "auth rate limited"
|
|
|
|
def test_update_credentials(self, auth_service):
|
|
auth_service.update_credentials(token="new_token", password="new_password")
|
|
assert auth_service._token == "new_token"
|
|
assert auth_service._password == "new_password"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_empty_header_with_credentials(self, auth_service, mock_rate_limiter):
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
mock_rate_limiter.check_and_incr.return_value = True
|
|
passed, reason = await auth_service.authenticate("")
|
|
assert passed is False
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_authenticate_malformed_basic(self, auth_service, mock_rate_limiter):
|
|
mock_rate_limiter.is_locked.return_value = (False, 0)
|
|
mock_rate_limiter.check_and_incr.return_value = True
|
|
passed, reason = await auth_service.authenticate("Basic invalid_base64!!!")
|
|
assert passed is False
|