Files
sientia-dataops-scouter_tem…/e2e/fixtures/fake_mongodb_repository.py
vitor-aignosi b17eaf972c SIENTIAPDE-1445
Update requirements-dev.txt to add E2E testing dependencies: fakeredis and mongomock for in-memory testing, and include testcontainers for PostgreSQL support.
2025-12-30 08:40:07 -03:00

242 lines
7.5 KiB
Python

"""
Fake MongoDB Repository adapter for testing.
This adapter implements the MongoDBRepository interface using mongomock
to provide an in-memory MongoDB server for testing.
"""
import time
from typing import Any
from mongomock import MongoClient
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
from sientia_do.observability.logger import Logger
from sientia_do.observability.metrics_controller import MetricsController
from sientia_do.observability.sientia_monitoring import SientiaMonitoring
def clear_mongo_id(docs: list) -> list:
"""
Remove MongoDB internal `_id` fields from nested structures.
Same implementation as in the real MongoDBRepository.
Args:
docs: The list of documents or nested structures to clean.
Returns:
The cleaned documents with `_id` fields removed wherever present.
"""
for doc in docs:
if isinstance(doc, list):
clear_mongo_id(doc)
elif isinstance(doc, dict):
if '_id' in doc:
del doc['_id']
for _key, value in doc.items():
if isinstance(value, list):
clear_mongo_id(value)
elif isinstance(value, dict):
clear_mongo_id([value])
return docs
class FakeMongoDBRepository(SientiaMonitoring):
"""
Fake MongoDB Repository that uses mongomock for testing.
Implements the same interface as MongoDBRepository but uses
mongomock for in-memory MongoDB operations.
"""
def __init__(
self,
connection_string: str,
database_name: str,
logger: Logger,
notification_handler: NotificationHandler,
metrics_controller: MetricsController,
):
"""
Initialize fake MongoDB repository with mongomock.
Args:
connection_string: MongoDB connection string (ignored in fake mode)
database_name: Target database name
logger: Logger instance
notification_handler: Notification handler
metrics_controller: Metrics controller
"""
SientiaMonitoring.__init__(
self,
logger=logger,
notification_handler=notification_handler,
metrics_controller=metrics_controller,
)
self.database_name = database_name
# Use mongomock instead of real MongoDB
self.mongo_client = MongoClient()
self.database = self.mongo_client[self.database_name]
logger.info('Fake MongoDB connection initialized')
def close(self):
"""
Closes fake MongoDB connection and shuts down monitoring.
"""
try:
if self.mongo_client:
self.logger.info('Closing fake MongoDB connection...')
self.mongo_client.close()
self.logger.info('Fake MongoDB connection closed successfully')
except Exception as e:
self.logger.error(f'Failed to close fake MongoDB connection: {e}')
SientiaMonitoring.shutdown(self)
def __del__(self):
"""
Destructor that closes the connection when destroying the instance.
"""
self.close()
async def find(
self,
collection_name: str,
filters: dict[str, Any],
metadata: dict[str, Any],
) -> list[dict[str, Any]]:
"""
Finds documents in a MongoDB collection based on provided filters.
Args:
collection_name: Name of the collection to search
filters: Query filters to apply
metadata: Dictionary with additional metadata
Return:
List of documents matching the filters (with `_id` removed)
"""
try:
start_time = time.time()
collection = self.database[collection_name]
documents = list(collection.find(filters, {'_id': 0}))
except Exception as e:
self.logger.error(f'Failed to find documents in fake MongoDB: {e}')
raise e
return clear_mongo_id(documents)
async def aggregate(
self,
collection_name: str,
pipeline: list[dict[str, Any]],
metadata: dict[str, Any],
) -> list[dict[str, Any]]:
"""
Executes an aggregation on a MongoDB collection.
Args:
collection_name: Name of the collection to aggregate
pipeline: MongoDB aggregation pipeline
metadata: Dictionary with additional metadata
Return:
List of documents resulting from aggregation (with `_id` removed)
"""
try:
start_time = time.time()
collection = self.database[collection_name]
documents = list(collection.aggregate(pipeline))
except Exception as e:
self.logger.error(f'Failed to aggregate documents in fake MongoDB: {e}')
raise e
return clear_mongo_id(documents)
async def update_many(
self,
collection_name: str,
filters: dict[str, Any],
update: dict[str, Any],
metadata: dict[str, Any],
) -> None:
"""
Updates multiple documents in a MongoDB collection.
Args:
collection_name: Collection name
filters: Filters to identify documents to update
update: Update operations to apply
metadata: Dictionary with additional metadata
"""
try:
collection = self.database[collection_name]
collection.update_many(filters, update)
except Exception as e:
self.logger.error(f'Failed to update documents in fake MongoDB: {e}')
raise e
async def insert_many(
self,
collection_name: str,
documents: list[dict[str, Any]],
metadata: dict[str, Any],
) -> None:
"""
Inserts multiple documents into a MongoDB collection.
Args:
collection_name: Collection name
documents: List of documents to insert
metadata: Dictionary with additional metadata
"""
try:
collection = self.database[collection_name]
collection.insert_many(documents)
except Exception as e:
self.logger.error(f'Failed to insert documents in fake MongoDB: {e}')
raise e
async def insert(
self,
collection_name: str,
document: dict[str, Any],
metadata: dict[str, Any],
) -> None:
"""
Inserts a document into a MongoDB collection.
Args:
collection_name: Collection name
document: Document to insert
metadata: Dictionary with additional metadata
"""
try:
collection = self.database[collection_name]
collection.insert_one(document)
except Exception as e:
self.logger.error(f'Failed to insert document in fake MongoDB: {e}')
raise e
async def delete_many(
self,
collection_name: str,
filters: dict[str, Any],
metadata: dict[str, Any],
) -> None:
"""
Removes multiple documents from a MongoDB collection.
Args:
collection_name: Collection name
filters: Filters to identify documents to remove
metadata: Dictionary with additional metadata
"""
try:
collection = self.database[collection_name]
collection.delete_many(filters)
except Exception as e:
self.logger.error(f'Failed to delete documents in fake MongoDB: {e}')
raise e