Talent-Lens / tests /unit /test_embedding.py
riezqidr's picture
fix(search): connect ingestion to search and remove SQL injection
86108cc
Raw
History Blame Contribute Delete
3.41 kB
"""Tests for embedding service and mock adapter.
The mock embedder is what lets unit tests run without a live TEI instance. If it
silently produces the wrong dimension or fails to honor the protocol, every test
using it becomes unreliable.
"""
from __future__ import annotations
import pytest
from app.services.embedding import (
MockEmbeddingService,
get_embedding_service,
reset_embedding_service,
set_embedding_service,
)
@pytest.mark.asyncio
async def test_mock_embedding_service_returns_correct_dimension():
embedder = MockEmbeddingService(dimension=512)
vector = await embedder.embed_query("test query")
assert len(vector) == 512
@pytest.mark.asyncio
async def test_mock_embedding_service_batch_returns_one_vector_per_text():
embedder = MockEmbeddingService(dimension=128)
vectors = await embedder.embed_texts(["first", "second", "third"])
assert len(vectors) == 3
assert all(len(v) == 128 for v in vectors)
@pytest.mark.asyncio
async def test_mock_embedding_service_empty_batch_returns_empty_list():
embedder = MockEmbeddingService(dimension=128)
vectors = await embedder.embed_texts([])
assert vectors == []
def test_mock_embedding_service_exposes_model_name():
embedder = MockEmbeddingService(dimension=64)
assert embedder.model_name == "mock-embedder"
def test_mock_embedding_service_exposes_model_version():
embedder = MockEmbeddingService(dimension=64)
assert embedder.model_version == "test-v1"
def test_mock_embedding_service_exposes_dimension():
embedder = MockEmbeddingService(dimension=256)
assert embedder.dimension == 256
@pytest.mark.asyncio
async def test_mock_embedding_service_embed_texts_is_awaitable():
"""The protocol requires async, so the mock must match."""
embedder = MockEmbeddingService(dimension=64)
vectors = await embedder.embed_texts(["async test"])
assert len(vectors) == 1
assert len(vectors[0]) == 64
@pytest.mark.asyncio
async def test_mock_embedding_service_embed_query_is_awaitable():
embedder = MockEmbeddingService(dimension=64)
vector = await embedder.embed_query("async query")
assert len(vector) == 64
def test_singleton_returns_an_embedding_service():
"""The singleton must return something that satisfies the protocol."""
reset_embedding_service()
service = get_embedding_service()
assert hasattr(service, "model_name")
assert hasattr(service, "model_version")
assert hasattr(service, "dimension")
assert hasattr(service, "embed_texts")
assert hasattr(service, "embed_query")
def test_singleton_returns_the_same_instance_on_repeated_calls():
reset_embedding_service()
first = get_embedding_service()
second = get_embedding_service()
assert first is second
def test_set_embedding_service_overrides_the_singleton():
"""Tests need to inject a mock without network calls."""
reset_embedding_service()
mock = MockEmbeddingService(dimension=32)
set_embedding_service(mock)
retrieved = get_embedding_service()
assert retrieved is mock
def test_reset_embedding_service_clears_the_singleton():
set_embedding_service(MockEmbeddingService(dimension=16))
reset_embedding_service()
after_reset = get_embedding_service()
# After reset, the singleton rebuilds from config, so it's a new instance
assert after_reset is not None