1e3dc11d59
feat(test-suite): 新增测试套件模块,包含API测试客户端和测试配置 fix(api): 修复数据库实体和仓库的删除操作返回值 style(api): 统一数据库表名和字段命名 perf(api): 添加缓存注解提升配置查询性能 test(api): 添加H2测试数据库配置支持 chore: 清理旧的测试文件和脚本
350 lines
9.2 KiB
Python
350 lines
9.2 KiB
Python
"""
|
|
单元测试套件 - API客户端测试
|
|
|
|
测试范围:
|
|
1. API客户端基础功能
|
|
2. 认证API测试
|
|
3. 用户API测试
|
|
4. 角色API测试
|
|
|
|
作者: 张翔
|
|
日期: 2026-04-01
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, AsyncMock, patch
|
|
from api.base_api import BaseAPIClient, AsyncAPIClient
|
|
from api.auth_api import AuthAPI
|
|
from api.user_api import UserAPI
|
|
from api.role_api import RoleAPI
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestBaseAPI:
|
|
"""API客户端基础功能测试"""
|
|
|
|
def test_base_api_initialization(self):
|
|
"""
|
|
UNIT-API-01: API客户端初始化测试
|
|
|
|
验证点:
|
|
1. 正确初始化客户端
|
|
2. 设置基础URL
|
|
3. 设置超时时间
|
|
"""
|
|
base_url = "http://localhost:8084"
|
|
|
|
api = BaseAPIClient(base_url=base_url, timeout=30)
|
|
|
|
assert api.base_url == base_url
|
|
assert api.timeout == 30
|
|
assert api.session is not None
|
|
|
|
def test_api_headers_generation(self):
|
|
"""
|
|
UNIT-API-02: API请求头生成测试
|
|
|
|
验证点:
|
|
1. 正确生成基础请求头
|
|
2. 包含认证Token时添加Authorization
|
|
"""
|
|
api = BaseAPIClient()
|
|
api.token = "test_token_123"
|
|
|
|
headers = api._get_headers(include_auth=True)
|
|
|
|
assert "Content-Type" in headers
|
|
assert "Authorization" in headers
|
|
assert headers["Authorization"] == "Bearer test_token_123"
|
|
|
|
headers_no_auth = api._get_headers(include_auth=False)
|
|
assert "Authorization" not in headers_no_auth
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestAuthAPI:
|
|
"""认证API测试"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_success(self):
|
|
"""
|
|
UNIT-AUTH-01: 登录成功测试
|
|
|
|
验证点:
|
|
1. 正确发送登录请求
|
|
2. 返回Token
|
|
3. 返回用户信息
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.post = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=200,
|
|
json=Mock(return_value={
|
|
"token": "test_token_123",
|
|
"userId": 1,
|
|
"username": "admin"
|
|
})
|
|
)
|
|
)
|
|
|
|
auth_api = AuthAPI(mock_client)
|
|
|
|
response = await auth_api.login("admin", "admin123")
|
|
|
|
assert response.status_code == 200
|
|
assert response.json()["token"] == "test_token_123"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_login_failure(self):
|
|
"""
|
|
UNIT-AUTH-02: 登录失败测试
|
|
|
|
验证点:
|
|
1. 错误密码返回401
|
|
2. 错误信息不泄露敏感信息
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.post = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=401,
|
|
json=Mock(return_value={
|
|
"error": "Invalid credentials"
|
|
})
|
|
)
|
|
)
|
|
|
|
auth_api = AuthAPI(mock_client)
|
|
|
|
response = await auth_api.login("admin", "wrong_password")
|
|
|
|
assert response.status_code == 401
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_logout(self):
|
|
"""
|
|
UNIT-AUTH-03: 登出测试
|
|
|
|
验证点:
|
|
1. 正确发送登出请求
|
|
2. 返回成功状态
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.post = AsyncMock(
|
|
return_value=Mock(status_code=200)
|
|
)
|
|
|
|
auth_api = AuthAPI(mock_client)
|
|
|
|
response = await auth_api.logout()
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestUserAPI:
|
|
"""用户API测试"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_users_by_page(self):
|
|
"""
|
|
UNIT-USER-01: 分页获取用户列表测试
|
|
|
|
验证点:
|
|
1. 正确发送分页参数
|
|
2. 返回分页数据
|
|
3. 包含总数信息
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.get = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=200,
|
|
json=Mock(return_value={
|
|
"content": [
|
|
{"id": 1, "username": "admin"},
|
|
{"id": 2, "username": "user"}
|
|
],
|
|
"totalElements": 2,
|
|
"totalPages": 1,
|
|
"size": 10,
|
|
"number": 0
|
|
})
|
|
)
|
|
)
|
|
|
|
user_api = UserAPI(mock_client)
|
|
|
|
response = await user_api.get_users_by_page(page=0, size=10)
|
|
|
|
assert response.status_code == 200
|
|
assert len(response.json()["content"]) == 2
|
|
assert response.json()["totalElements"] == 2
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_user(self):
|
|
"""
|
|
UNIT-USER-02: 创建用户测试
|
|
|
|
验证点:
|
|
1. 正确发送用户数据
|
|
2. 返回创建的用户ID
|
|
3. 验证必填字段
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.post = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=201,
|
|
json=Mock(return_value={
|
|
"id": 3,
|
|
"username": "new_user",
|
|
"email": "new_user@test.com"
|
|
})
|
|
)
|
|
)
|
|
|
|
user_api = UserAPI(mock_client)
|
|
|
|
user_data = {
|
|
"username": "new_user",
|
|
"password": "Test123!@#",
|
|
"email": "new_user@test.com",
|
|
"phone": "13800138000"
|
|
}
|
|
|
|
response = await user_api.create_user(user_data)
|
|
|
|
assert response.status_code == 201
|
|
assert response.json()["id"] == 3
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_user(self):
|
|
"""
|
|
UNIT-USER-03: 更新用户测试
|
|
|
|
验证点:
|
|
1. 正确发送更新数据
|
|
2. 返回更新后的用户信息
|
|
3. 部分更新支持
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.put = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=200,
|
|
json=Mock(return_value={
|
|
"id": 1,
|
|
"email": "updated@test.com"
|
|
})
|
|
)
|
|
)
|
|
|
|
user_api = UserAPI(mock_client)
|
|
|
|
update_data = {"email": "updated@test.com"}
|
|
|
|
response = await user_api.update_user(1, update_data)
|
|
|
|
assert response.status_code == 200
|
|
assert response.json()["email"] == "updated@test.com"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_user(self):
|
|
"""
|
|
UNIT-USER-04: 删除用户测试
|
|
|
|
验证点:
|
|
1. 正确发送删除请求
|
|
2. 返回成功状态
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.delete = AsyncMock(
|
|
return_value=Mock(status_code=204)
|
|
)
|
|
|
|
user_api = UserAPI(mock_client)
|
|
|
|
response = await user_api.delete_user(1)
|
|
|
|
assert response.status_code == 204
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_search_users(self):
|
|
"""
|
|
UNIT-USER-05: 搜索用户测试
|
|
|
|
验证点:
|
|
1. 正确发送搜索关键词
|
|
2. 返回匹配结果
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.get = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=200,
|
|
json=Mock(return_value={
|
|
"content": [
|
|
{"id": 1, "username": "admin"}
|
|
],
|
|
"totalElements": 1
|
|
})
|
|
)
|
|
)
|
|
|
|
user_api = UserAPI(mock_client)
|
|
|
|
response = await user_api.get_users_by_page(username="admin")
|
|
|
|
assert response.status_code == 200
|
|
assert len(response.json()["content"]) == 1
|
|
|
|
|
|
@pytest.mark.unit
|
|
class TestRoleAPI:
|
|
"""角色API测试"""
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_get_roles(self):
|
|
"""
|
|
UNIT-ROLE-01: 获取角色列表测试
|
|
|
|
验证点:
|
|
1. 正确返回角色列表
|
|
2. 包含角色权限信息
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.get = AsyncMock(
|
|
return_value=Mock(
|
|
status_code=200,
|
|
json=Mock(return_value=[
|
|
{"id": 1, "roleName": "管理员", "roleKey": "admin"},
|
|
{"id": 2, "roleName": "普通用户", "roleKey": "user"}
|
|
])
|
|
)
|
|
)
|
|
|
|
role_api = RoleAPI(mock_client)
|
|
|
|
response = await role_api.get_role_list()
|
|
|
|
assert response.status_code == 200
|
|
assert len(response.json()) == 2
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_assign_permissions(self):
|
|
"""
|
|
UNIT-ROLE-02: 分配权限测试
|
|
|
|
验证点:
|
|
1. 正确发送权限数据
|
|
2. 返回成功状态
|
|
"""
|
|
mock_client = Mock()
|
|
mock_client.post = AsyncMock(
|
|
return_value=Mock(status_code=200)
|
|
)
|
|
|
|
role_api = RoleAPI(mock_client)
|
|
|
|
permission_ids = [1, 2, 3]
|
|
|
|
response = await role_api.assign_permissions(1, permission_ids)
|
|
|
|
assert response.status_code == 200
|