Files
xiaoxia-saas/tests/unit/test_in_memory_repositories.py
CI Bot 18bd0de3fa
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 1m42s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 1m44s
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m42s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 1m26s
CI/CD Pipeline / Validate - Code Quality (push) Failing after 3m13s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m22s
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Successful in 4m29s
CI/CD Pipeline / Integration Tests (push) Successful in 2m16s
CI/CD Pipeline / Unit Tests (push) Failing after 5m46s
CI/CD Pipeline / Build Staging API Image (push) Successful in 11m28s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m18s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 30s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 2m13s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 5m58s
style: auto-format with black + isort + prettier
2026-07-24 14:07:12 +00:00

204 lines
6.4 KiB
Python
Executable File

"""
In-Memory 项目仓储 + 小仓储测试.
"""
from __future__ import annotations
from datetime import datetime
import pytest
from packages.adapters.in_memory.classification_job_repository import InMemoryClassificationJobRepository
from packages.adapters.in_memory.ingest_job_repository import InMemoryIngestJobRepository
from packages.adapters.in_memory.project_repository import InMemoryProjectRepository
from packages.domain import ClassificationJob, IngestJob, Project
# ── Project Repository ──────────────────────────────────────────────────────
@pytest.fixture
def project_repo():
return InMemoryProjectRepository()
@pytest.fixture
def make_project():
counter = 0
def _make(owner_id: str = "user_1", name: str = "测试项目"):
nonlocal counter
counter += 1
return Project(
id=f"proj_{counter}",
owner_user_id=owner_id,
name=name,
)
return _make
class TestInMemoryProjectRepository:
"""项目仓储."""
def test_save_and_find_by_id(self, project_repo, make_project):
proj = make_project()
project_repo.save(proj)
found = project_repo.find_by_id(proj.id)
assert found is not None
assert found.id == proj.id
assert found.name == "测试项目"
def test_find_by_id_not_found(self, project_repo):
assert project_repo.find_by_id("nonexistent") is None
def test_find_by_owner(self, project_repo, make_project):
for i in range(3):
project_repo.save(make_project(owner_id="user_1", name=f"p{i}"))
project_repo.save(make_project(owner_id="user_2", name="other"))
result = project_repo.find_by_owner_user_id("user_1")
assert len(result) == 3
assert all(p.owner_user_id == "user_1" for p in result)
def test_count_by_owner(self, project_repo, make_project):
for i in range(5):
project_repo.save(make_project(owner_id="user_1", name=f"p{i}"))
project_repo.save(make_project(owner_id="user_2", name="other"))
assert project_repo.count_by_owner("user_1") == 5
assert project_repo.count_by_owner("user_2") == 1
assert project_repo.count_by_owner("user_3") == 0
def test_delete_existing(self, project_repo, make_project):
proj = make_project()
project_repo.save(proj)
result = project_repo.delete(proj.id)
assert result is True
assert project_repo.find_by_id(proj.id) is None
def test_delete_nonexistent(self, project_repo):
assert project_repo.delete("nonexistent") is False
def test_save_updates(self, project_repo, make_project):
proj = make_project(name="v1")
project_repo.save(proj)
proj.name = "v2"
project_repo.save(proj)
found = project_repo.find_by_id(proj.id)
assert found.name == "v2"
def test_find_accessible_projects(self, project_repo, make_project):
p1 = make_project(owner_id="user_1", name="owned")
project_repo.save(p1)
# 自己拥有的项目可访问
result = project_repo.find_accessible_projects("user_1")
assert len(result) >= 1
assert any(p.id == p1.id for p in result)
# ── Classification Job Repository ──────────────────────────────────────────
@pytest.fixture
def classif_repo():
return InMemoryClassificationJobRepository()
class TestInMemoryClassificationJobRepository:
"""分类任务仓储."""
def test_create_and_get(self, classif_repo):
job = ClassificationJob(
id="job_1",
project_id="p1",
asset_id="a1",
status="pending",
)
classif_repo.create(job)
found = classif_repo.get("job_1")
assert found is not None
assert found.id == "job_1"
assert found.status == "pending"
def test_get_not_found(self, classif_repo):
assert classif_repo.get("nonexistent") is None
def test_update(self, classif_repo):
job = ClassificationJob(
id="job_1",
project_id="p1",
asset_id="a1",
status="pending",
)
classif_repo.create(job)
job.status = "completed"
classif_repo.update(job)
found = classif_repo.get("job_1")
assert found.status == "completed"
def test_update_nonexistent_creates(self, classif_repo):
"""update 对不存在的也会写入(dict 赋值)"""
job = ClassificationJob(
id="new_job",
project_id="p1",
asset_id="a1",
status="running",
)
classif_repo.update(job)
found = classif_repo.get("new_job")
assert found is not None
# ── Ingest Job Repository ──────────────────────────────────────────────────
@pytest.fixture
def ingest_repo():
return InMemoryIngestJobRepository()
class TestInMemoryIngestJobRepository:
"""导入任务仓储."""
def test_create_and_get(self, ingest_repo):
job = IngestJob(
id="ingest_1",
project_id="p1",
library_id="lib1",
storage_key="key1",
status="pending",
)
ingest_repo.create(job)
found = ingest_repo.get("ingest_1")
assert found is not None
assert found.id == "ingest_1"
assert found.status == "pending"
def test_get_not_found(self, ingest_repo):
assert ingest_repo.get("nonexistent") is None
def test_update(self, ingest_repo):
job = IngestJob(
id="ingest_1",
project_id="p1",
library_id="lib1",
storage_key="key1",
status="pending",
)
ingest_repo.create(job)
job.status = "completed"
ingest_repo.update(job)
found = ingest_repo.get("ingest_1")
assert found.status == "completed"
def test_update_nonexistent_creates(self, ingest_repo):
job = IngestJob(
id="new_ingest",
project_id="p1",
library_id="lib1",
storage_key="key1",
status="running",
)
ingest_repo.update(job)
found = ingest_repo.get("new_ingest")
assert found is not None