dify/api/tests/unit_tests/controllers/service_api/conftest.py
Asuka Minato 01efc6eecb
test: use SQLite sessions in service API fixtures (#38784)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-22 04:51:49 +00:00

212 lines
5.8 KiB
Python

"""
Shared fixtures for Service API controller tests.
This module provides reusable fixtures for mocking authentication,
database interactions, and common test data patterns used across
Service API controller tests.
"""
import uuid
from collections.abc import Iterator
from dataclasses import dataclass
from unittest.mock import Mock
import pytest
from flask import Flask
from sqlalchemy import Engine
from sqlalchemy.orm import Session
from core.rag.index_processor.constant.index_type import IndexStructureType
from models.account import Account, Tenant, TenantAccountJoin, TenantAccountRole, TenantStatus
from models.base import TypeBase
from models.model import App, AppMode, EndUser
@dataclass(frozen=True)
class ServiceApiIdentity:
"""Persisted owner identity for service-API authentication tests."""
session: Session
tenant: Tenant
account: Account
membership: TenantAccountJoin
@pytest.fixture
def service_api_identity(sqlite_engine: Engine) -> Iterator[ServiceApiIdentity]:
"""Yield an isolated SQLite session with a real active tenant owner."""
TypeBase.metadata.create_all(
sqlite_engine,
tables=[Account.__table__, Tenant.__table__, TenantAccountJoin.__table__],
)
with Session(sqlite_engine, expire_on_commit=False) as session:
tenant = Tenant(name="Service API Workspace")
tenant.id = str(uuid.uuid4())
account = Account(name="Service API Owner", email=f"owner-{tenant.id}@example.com")
account.id = str(uuid.uuid4())
membership = TenantAccountJoin(
tenant_id=tenant.id,
account_id=account.id,
role=TenantAccountRole.OWNER,
)
account._current_tenant = tenant
session.add_all([tenant, account, membership])
session.commit()
yield ServiceApiIdentity(
session=session,
tenant=tenant,
account=account,
membership=membership,
)
@pytest.fixture
def app():
"""Create Flask test application with proper configuration."""
flask_app = Flask(__name__)
flask_app.config["TESTING"] = True
return flask_app
@pytest.fixture
def mock_tenant_id():
"""Generate a consistent tenant ID for test sessions."""
return str(uuid.uuid4())
@pytest.fixture
def mock_app_id():
"""Generate a consistent app ID for test sessions."""
return str(uuid.uuid4())
@pytest.fixture
def mock_end_user(mock_tenant_id):
"""Create a mock EndUser model with required attributes."""
user = Mock(spec=EndUser)
user.id = str(uuid.uuid4())
user.external_user_id = f"external_{uuid.uuid4().hex[:8]}"
user.tenant_id = mock_tenant_id
return user
@pytest.fixture
def mock_app_model(mock_app_id, mock_tenant_id):
"""Create a mock App model with all required attributes for API testing."""
app = Mock(spec=App)
app.id = mock_app_id
app.tenant_id = mock_tenant_id
app.name = "Test App"
app.description = "A test application"
app.mode = AppMode.CHAT
app.author_name = "Test Author"
app.status = "normal"
app.enable_api = True
app.tags = []
# Mock workflow for workflow apps
app.workflow = None
app.app_model_config = None
return app
@pytest.fixture
def mock_tenant(mock_tenant_id):
"""Create a mock Tenant model."""
tenant = Mock()
tenant.id = mock_tenant_id
tenant.status = TenantStatus.NORMAL
return tenant
@pytest.fixture
def mock_account():
"""Create a mock Account model."""
account = Mock()
account.id = str(uuid.uuid4())
return account
@pytest.fixture
def mock_api_token(mock_app_id, mock_tenant_id):
"""Create a mock API token for authentication tests."""
token = Mock()
token.app_id = mock_app_id
token.tenant_id = mock_tenant_id
token.token = f"test_token_{uuid.uuid4().hex[:8]}"
token.type = "app"
return token
@pytest.fixture
def mock_dataset_api_token(mock_tenant_id):
"""Create a mock API token for dataset endpoints."""
token = Mock()
token.tenant_id = mock_tenant_id
token.token = f"dataset_token_{uuid.uuid4().hex[:8]}"
token.type = "dataset"
return token
@pytest.fixture
def mock_dataset():
"""Create a mock Dataset model."""
from models.dataset import Dataset
dataset = Mock(spec=Dataset)
dataset.id = str(uuid.uuid4())
dataset.tenant_id = str(uuid.uuid4())
dataset.name = "Test Dataset"
dataset.indexing_technique = "economy"
dataset.embedding_model = None
dataset.embedding_model_provider = None
return dataset
@pytest.fixture
def mock_document():
"""Create a mock Document model."""
from models.dataset import Document
document = Mock(spec=Document)
document.id = str(uuid.uuid4())
document.dataset_id = str(uuid.uuid4())
document.tenant_id = str(uuid.uuid4())
document.name = "test_document.txt"
document.indexing_status = "completed"
document.enabled = True
document.doc_form = IndexStructureType.PARAGRAPH_INDEX
return document
@pytest.fixture
def mock_segment():
"""Create a mock DocumentSegment model."""
from models.dataset import DocumentSegment
segment = Mock(spec=DocumentSegment)
segment.id = str(uuid.uuid4())
segment.document_id = str(uuid.uuid4())
segment.dataset_id = str(uuid.uuid4())
segment.tenant_id = str(uuid.uuid4())
segment.content = "Test segment content"
segment.word_count = 3
segment.position = 1
segment.enabled = True
segment.status = "completed"
return segment
@pytest.fixture
def mock_child_chunk():
"""Create a mock ChildChunk model."""
from models.dataset import ChildChunk
child_chunk = Mock(spec=ChildChunk)
child_chunk.id = str(uuid.uuid4())
child_chunk.segment_id = str(uuid.uuid4())
child_chunk.tenant_id = str(uuid.uuid4())
child_chunk.content = "Test child chunk content"
return child_chunk