194 lines
7.0 KiB
Python
194 lines
7.0 KiB
Python
"""
|
|
Unit tests for MongoDB database connection module.
|
|
|
|
Tests the database connection functionality with mocking
|
|
to avoid requiring actual MongoDB instance during tests.
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import Mock, patch, MagicMock
|
|
from pymongo.errors import ConnectionFailure, ServerSelectionTimeoutError
|
|
|
|
from app.database.connection import (
|
|
create_mongodb_client,
|
|
get_database,
|
|
close_database_connection,
|
|
get_mongodb_client,
|
|
test_database_connection
|
|
)
|
|
|
|
|
|
def test_i_can_get_database_connection():
|
|
"""Test successful database connection creation."""
|
|
mock_client = Mock()
|
|
mock_database = Mock()
|
|
mock_client.__getitem__.return_value = mock_database
|
|
|
|
with patch('app.database.connection.MongoClient', return_value=mock_client):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://localhost:27017"):
|
|
with patch('app.database.connection.get_mongodb_database_name', return_value="testdb"):
|
|
# Reset global variables
|
|
import app.database.connection
|
|
app.database.connection._client = None
|
|
app.database.connection._database = None
|
|
|
|
result = get_database()
|
|
|
|
assert result == mock_database
|
|
mock_client.admin.command.assert_called_with('ping')
|
|
|
|
|
|
def test_i_cannot_connect_to_invalid_mongodb_url():
|
|
"""Test fail-fast behavior with invalid MongoDB URL."""
|
|
mock_client = Mock()
|
|
mock_client.admin.command.side_effect = ConnectionFailure("Connection failed")
|
|
|
|
with patch('app.database.connection.MongoClient', return_value=mock_client):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://invalid:27017"):
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
create_mongodb_client()
|
|
|
|
assert exc_info.value.code == 1
|
|
|
|
|
|
def test_i_cannot_connect_with_server_selection_timeout():
|
|
"""Test fail-fast behavior with server selection timeout."""
|
|
mock_client = Mock()
|
|
mock_client.admin.command.side_effect = ServerSelectionTimeoutError("Timeout")
|
|
|
|
with patch('app.database.connection.MongoClient', return_value=mock_client):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://timeout:27017"):
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
create_mongodb_client()
|
|
|
|
assert exc_info.value.code == 1
|
|
|
|
|
|
def test_i_cannot_connect_with_unexpected_error():
|
|
"""Test fail-fast behavior with unexpected connection error."""
|
|
with patch('app.database.connection.MongoClient', side_effect=Exception("Unexpected error")):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://error:27017"):
|
|
with pytest.raises(SystemExit) as exc_info:
|
|
create_mongodb_client()
|
|
|
|
assert exc_info.value.code == 1
|
|
|
|
|
|
def test_i_can_get_database_singleton():
|
|
"""Test that get_database returns the same instance (singleton pattern)."""
|
|
mock_client = Mock()
|
|
mock_database = Mock()
|
|
mock_client.__getitem__.return_value = mock_database
|
|
|
|
with patch('app.database.connection.MongoClient', return_value=mock_client):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://localhost:27017"):
|
|
with patch('app.database.connection.get_mongodb_database_name', return_value="testdb"):
|
|
# Reset global variables
|
|
import app.database.connection
|
|
app.database.connection._client = None
|
|
app.database.connection._database = None
|
|
|
|
# First call
|
|
db1 = get_database()
|
|
# Second call
|
|
db2 = get_database()
|
|
|
|
assert db1 is db2
|
|
# MongoClient should be called only once
|
|
assert mock_client.admin.command.call_count == 1
|
|
|
|
|
|
def test_i_can_close_database_connection():
|
|
"""Test closing database connection."""
|
|
mock_client = Mock()
|
|
mock_database = Mock()
|
|
mock_client.__getitem__.return_value = mock_database
|
|
|
|
with patch('app.database.connection.MongoClient', return_value=mock_client):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://localhost:27017"):
|
|
with patch('app.database.connection.get_mongodb_database_name', return_value="testdb"):
|
|
# Reset global variables
|
|
import app.database.connection
|
|
app.database.connection._client = None
|
|
app.database.connection._database = None
|
|
|
|
# Create connection
|
|
get_database()
|
|
|
|
# Close connection
|
|
close_database_connection()
|
|
|
|
mock_client.close.assert_called_once()
|
|
assert app.database.connection._client is None
|
|
assert app.database.connection._database is None
|
|
|
|
|
|
def test_i_can_get_mongodb_client():
|
|
"""Test getting raw MongoDB client instance."""
|
|
mock_client = Mock()
|
|
mock_database = Mock()
|
|
mock_client.__getitem__.return_value = mock_database
|
|
|
|
with patch('app.database.connection.MongoClient', return_value=mock_client):
|
|
with patch('app.database.connection.get_mongodb_url', return_value="mongodb://localhost:27017"):
|
|
with patch('app.database.connection.get_mongodb_database_name', return_value="testdb"):
|
|
# Reset global variables
|
|
import app.database.connection
|
|
app.database.connection._client = None
|
|
app.database.connection._database = None
|
|
|
|
# Create connection first
|
|
get_database()
|
|
|
|
# Get client
|
|
result = get_mongodb_client()
|
|
|
|
assert result == mock_client
|
|
|
|
|
|
def test_i_can_get_none_mongodb_client_when_not_connected():
|
|
"""Test getting MongoDB client returns None when not connected."""
|
|
# Reset global variables
|
|
import app.database.connection
|
|
app.database.connection._client = None
|
|
app.database.connection._database = None
|
|
|
|
result = get_mongodb_client()
|
|
assert result is None
|
|
|
|
|
|
def test_i_can_test_database_connection_success():
|
|
"""Test database connection health check - success case."""
|
|
mock_database = Mock()
|
|
mock_database.command.return_value = True
|
|
|
|
with patch('app.database.connection.get_database', return_value=mock_database):
|
|
result = test_database_connection()
|
|
|
|
assert result is True
|
|
mock_database.command.assert_called_with('ping')
|
|
|
|
|
|
def test_i_cannot_test_database_connection_failure():
|
|
"""Test database connection health check - failure case."""
|
|
mock_database = Mock()
|
|
mock_database.command.side_effect = Exception("Connection error")
|
|
|
|
with patch('app.database.connection.get_database', return_value=mock_database):
|
|
result = test_database_connection()
|
|
|
|
assert result is False
|
|
|
|
|
|
def test_i_can_close_connection_when_no_client():
|
|
"""Test closing connection when no client exists (should not raise error)."""
|
|
# Reset global variables
|
|
import app.database.connection
|
|
app.database.connection._client = None
|
|
app.database.connection._database = None
|
|
|
|
# Should not raise any exception
|
|
close_database_connection()
|
|
|
|
assert app.database.connection._client is None
|
|
assert app.database.connection._database is None |