Files
FastapiAdmin/backend/tests/test_unit.py
T
zhangtao 17b3cd0a4c refactor: 完成系统架构升级与模块拆分
本次提交进行了大规模的系统重构:
1. 拆分租户相关模块到platform平台层,重构租户表名与关联关系
2. 迁移日志、工单、插件等模块到对应层级,统一代码结构
3. 重构批量操作接口路径,从/available/setting改为/status/batch
4. 新增批量删除基础模型,统一处理批量操作逻辑
5. 优化导入导出接口,修正路由方法与描述信息
6. 修复循环引用问题,重构依赖注入与类型导入
7. 更新初始化脚本与路由注册,新增平台管理路由
8. 重构岗位模型,新增岗位编码字段与校验
9. 完善部门删除逻辑,新增子部门删除限制
10. 更新初始化数据与配置文件,适配新架构
2026-06-03 00:53:19 +08:00

212 lines
7.1 KiB
Python

"""多租户多模块纯单元测试(不依赖数据库连接)。"""
import pytest
# ==================== 01. 租户 ContextVar ====================
class TestTenantContextVar:
"""租户上下文变量读写与清理。"""
def test_initially_none(self) -> None:
from app.core.tenant import get_current_tenant_id, get_is_super_admin
assert get_current_tenant_id() is None
assert get_is_super_admin() is False
def test_set_and_get(self) -> None:
from app.core.tenant import (
clear_current_tenant,
get_current_tenant_id,
get_is_super_admin,
set_current_tenant,
)
set_current_tenant(42, True)
assert get_current_tenant_id() == 42
assert get_is_super_admin() is True
clear_current_tenant()
assert get_current_tenant_id() is None
# ==================== 02. ORM 模型定义 ====================
class TestModels:
"""核心业务模型表名与字段完整性。"""
def test_tenant_model(self) -> None:
from app.api.v1.module_platform.tenant.model import TenantModel
assert TenantModel.__tablename__ == "sys_tenant"
assert hasattr(TenantModel, "name")
assert hasattr(TenantModel, "code")
assert hasattr(TenantModel, "status")
assert hasattr(TenantModel, "end_time")
def test_tenant_quota_fields(self) -> None:
"""测试租户模型中的配额字段(单一大表设计)"""
from app.api.v1.module_platform.tenant.model import TenantModel
assert hasattr(TenantModel, "max_users")
assert hasattr(TenantModel, "max_roles")
assert hasattr(TenantModel, "max_storage_mb")
assert hasattr(TenantModel, "max_depts")
def test_tenant_config_model(self) -> None:
from app.api.v1.module_platform.tenant.model import TenantConfigModel
assert TenantConfigModel.__tablename__ == "sys_tenant_config"
assert hasattr(TenantConfigModel, "config_key")
def test_tenant_menu_model(self) -> None:
from app.api.v1.module_platform.tenant.model import TenantMenuModel
assert TenantMenuModel.__tablename__ == "sys_tenant_menu"
assert hasattr(TenantMenuModel, "menu_id")
def test_tenant_user_model(self) -> None:
from app.api.v1.module_platform.tenant.model import TenantUserModel
assert TenantUserModel.__tablename__ == "sys_user_tenant"
assert hasattr(TenantUserModel, "role")
assert hasattr(TenantUserModel, "is_default")
def test_user_model_has_tenant_id(self) -> None:
from app.api.v1.module_system.user.model import UserModel
assert hasattr(UserModel, "tenant_id")
assert hasattr(UserModel, "is_superuser")
def test_role_model_has_tenant_id(self) -> None:
from app.api.v1.module_system.role.model import RoleModel
assert hasattr(RoleModel, "tenant_id")
assert hasattr(RoleModel, "menus")
def test_menu_model_has_type(self) -> None:
from app.api.v1.module_system.menu.model import MenuModel
assert hasattr(MenuModel, "type")
assert hasattr(MenuModel, "name")
assert hasattr(MenuModel, "permission")
def test_notice_model(self) -> None:
from app.api.v1.module_system.notice.model import NoticeModel
assert NoticeModel.__tablename__ == "sys_notice"
assert hasattr(NoticeModel, "notice_title")
assert hasattr(NoticeModel, "status")
def test_plugin_model(self) -> None:
from app.api.v1.module_platform.plugin.model import PluginModel
assert PluginModel.__tablename__ == "sys_plugin"
assert hasattr(PluginModel, "code")
def test_tenant_plugin_model(self) -> None:
from app.api.v1.module_platform.plugin.model import TenantPluginModel
assert TenantPluginModel.__tablename__ == "sys_tenant_plugin"
def test_ticket_model(self) -> None:
from app.api.v1.module_platform.ticket.model import TicketModel
assert TicketModel.__tablename__ == "sys_ticket"
assert hasattr(TicketModel, "ticket_type")
assert hasattr(TicketModel, "reply")
# ==================== 03. Pydantic Schema ====================
class TestSchemas:
"""请求/响应Schema字段验证。"""
def test_tenant_create_schema(self) -> None:
from app.api.v1.module_platform.tenant.schema import TenantCreateSchema
s = TenantCreateSchema(name="test", code="test001", status="0")
assert s.name == "test"
assert s.code == "test001"
def test_tenant_update_schema_partial(self) -> None:
from app.api.v1.module_platform.tenant.schema import TenantUpdateSchema
s = TenantUpdateSchema(name="renamed")
assert s.name == "renamed"
assert s.code is None # 未传则为 None
def test_tenant_quota_schema_validation(self) -> None:
from app.api.v1.module_platform.tenant.schema import TenantQuotaUpdateSchema
s = TenantQuotaUpdateSchema(max_users=100, max_roles=30)
assert s.max_users == 100
# 负数应被拒绝
with pytest.raises(Exception):
TenantQuotaUpdateSchema(max_users=-1)
def test_ticket_schema(self) -> None:
from app.api.v1.module_platform.ticket.schema import TicketCreateSchema
s = TicketCreateSchema(title="test", ticket_type="suggestion")
assert s.title == "test"
assert s.ticket_type == "suggestion"
def test_menu_type_enum(self) -> None:
"""菜单类型: 1=目录 2=菜单 3=按钮 4=链接"""
from app.api.v1.module_system.menu.model import MenuModel
assert hasattr(MenuModel, "type")
# type 是 int 字段
# ==================== 04. 配置类 ====================
class TestSettings:
"""配置默认值与环境变量覆盖。"""
def test_settings_defaults(self) -> None:
from app.config.setting import settings
assert settings.DATABASE_HOST
assert settings.DATABASE_PORT > 0
assert settings.SERVER_PORT > 0
def test_redis_config(self) -> None:
from app.config.setting import settings
assert isinstance(settings.REDIS_ENABLE, bool)
assert settings.REDIS_PORT == 6379
def test_database_password_empty_by_default(self) -> None:
"""密码默认值为空,需通过 .env 或环境变量提供。"""
from app.config.setting import Settings
# 检查字段默认值(不依赖运行时环境变量)
assert Settings.model_fields["DATABASE_PASSWORD"].default == ""
# ==================== 05. 常量与枚举 ====================
class TestEnums:
"""业务枚举值完整性。"""
def test_status_operate_enum(self) -> None:
from app.common.enums import BusinessType
assert hasattr(BusinessType, "OTHER")
def test_menu_type_values(self) -> None:
"""type: 1=目录 2=菜单 3=按钮 4=链接"""
from app.api.v1.module_system.menu.model import MenuModel
assert MenuModel.__tablename__ == "sys_menu"
# type 字段是 int 类型
col = next((c for c in MenuModel.__table__.columns if c.name == "type"), None)
assert col is not None