ai-robot-core/ai-service/tests/test_field_roles_update.py

150 lines
4.9 KiB
Python

"""
Tests for field_roles update functionality.
[AC-MRS-01] 验证字段角色更新功能
"""
import pytest
import uuid
from unittest.mock import AsyncMock, MagicMock
from app.models.entities import (
MetadataFieldDefinition,
MetadataFieldDefinitionUpdate,
MetadataFieldStatus,
)
from app.services.metadata_field_definition_service import MetadataFieldDefinitionService
class TestFieldRolesUpdate:
"""测试字段角色更新功能"""
@pytest.fixture
def mock_session(self):
"""Create mock session"""
session = MagicMock()
session.execute = AsyncMock()
session.flush = AsyncMock()
session.commit = AsyncMock()
return session
@pytest.fixture
def service(self, mock_session):
"""Create service instance"""
return MetadataFieldDefinitionService(mock_session)
@pytest.fixture
def existing_field(self):
"""Create existing field with field_roles"""
field = MagicMock(spec=MetadataFieldDefinition)
field.id = uuid.uuid4()
field.tenant_id = "test-tenant"
field.field_key = "grade"
field.label = "年级"
field.type = "string"
field.required = True
field.options = None
field.default_value = None
field.scope = ["kb_document"]
field.is_filterable = True
field.is_rank_feature = False
field.field_roles = ["slot"] # 初始角色
field.status = MetadataFieldStatus.ACTIVE.value
field.version = 1
return field
@pytest.mark.asyncio
async def test_update_field_roles_success(self, service, mock_session, existing_field):
"""[AC-MRS-01] 测试成功更新字段角色"""
# Mock get_field_definition to return existing field
service.get_field_definition = AsyncMock(return_value=existing_field)
# Create update request with new field_roles
field_update = MetadataFieldDefinitionUpdate(
field_roles=["slot", "resource_filter"]
)
# Execute update
result = await service.update_field_definition(
"test-tenant",
str(existing_field.id),
field_update
)
# Verify result
assert result is not None
assert result.field_roles == ["slot", "resource_filter"]
assert result.version == 2 # Version should increment
@pytest.mark.asyncio
async def test_update_field_roles_to_empty(self, service, mock_session, existing_field):
"""[AC-MRS-01] 测试将字段角色更新为空列表"""
service.get_field_definition = AsyncMock(return_value=existing_field)
field_update = MetadataFieldDefinitionUpdate(
field_roles=[]
)
result = await service.update_field_definition(
"test-tenant",
str(existing_field.id),
field_update
)
assert result is not None
assert result.field_roles == []
@pytest.mark.asyncio
async def test_update_field_roles_invalid_role(self, service, mock_session, existing_field):
"""[AC-MRS-01] 测试更新无效的字段角色"""
service.get_field_definition = AsyncMock(return_value=existing_field)
field_update = MetadataFieldDefinitionUpdate(
field_roles=["invalid_role"]
)
with pytest.raises(ValueError) as exc_info:
await service.update_field_definition(
"test-tenant",
str(existing_field.id),
field_update
)
assert "无效的字段角色" in str(exc_info.value)
@pytest.mark.asyncio
async def test_update_without_field_roles_unchanged(self, service, mock_session, existing_field):
"""[AC-MRS-01] 测试不更新 field_roles 时保持原值"""
service.get_field_definition = AsyncMock(return_value=existing_field)
# Update only label, not field_roles
field_update = MetadataFieldDefinitionUpdate(
label="新年级标签"
)
result = await service.update_field_definition(
"test-tenant",
str(existing_field.id),
field_update
)
assert result is not None
assert result.label == "新年级标签"
assert result.field_roles == ["slot"] # Should remain unchanged
@pytest.mark.asyncio
async def test_update_field_roles_not_found(self, service, mock_session):
"""[AC-MRS-01] 测试更新不存在的字段"""
service.get_field_definition = AsyncMock(return_value=None)
field_update = MetadataFieldDefinitionUpdate(
field_roles=["slot"]
)
result = await service.update_field_definition(
"test-tenant",
str(uuid.uuid4()),
field_update
)
assert result is None