Coverage for tests/core_tests/test_mongodb_manager.py: 100%
214 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-05 14:02 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-05 14:02 +0000
1"""Test the MongoDB Manager class."""
3import os
4import sys
5from dotenv import load_dotenv
6import pytest
7from pymongo.errors import (
8 ConfigurationError,
9 OperationFailure,
10 ServerSelectionTimeoutError,
11 DuplicateKeyError,
12)
15# flake8: noqa: F811
17# Add the root directory to the Python path
18sys.path.append(
19 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
20)
21from core import shared
22from core.database_mongo_manager import DatabaseMongoManager
24os.environ["IS_TEST"] = "True"
26load_dotenv()
29@pytest.fixture()
30def database():
31 """Fixture to create a test database."""
32 DATABASE = DatabaseMongoManager(
33 shared.getenv("MONGO_URI"),
34 shared.getenv("MONGO_DB_TEST", "cs3528_testing"),
35 )
36 DATABASE.delete_all("test_collection") # Cleanup after tests
37 DATABASE.delete_collection("test_collection")
38 yield DATABASE
39 DATABASE.delete_all("test_collection") # Cleanup after tests
40 DATABASE.delete_collection("test_collection")
41 DATABASE.connection.close()
44def test_insert_and_get_by_id(database):
45 test_data = {"_id": "test1", "name": "Test Entry"}
46 database.insert("test_collection", test_data)
47 result = database.get_one_by_id("test_collection", "test1")
48 assert result is not None
49 assert result["name"] == "Test Entry"
50 database.delete_by_id("test_collection", "test1")
53def test_update_one_by_id(database):
54 test_data = {"_id": "test2", "name": "Initial Name"}
55 database.insert("test_collection", test_data)
56 database.update_one_by_id("test_collection", "test2", {"name": "Updated Name"})
57 updated = database.get_one_by_id("test_collection", "test2")
58 assert updated["name"] == "Updated Name"
59 database.delete_by_id("test_collection", "test2")
62def test_delete_by_id(database):
63 test_data = {"_id": "test3", "name": "To be deleted"}
64 database.insert("test_collection", test_data)
65 database.delete_by_id("test_collection", "test3")
66 deleted = database.get_one_by_id("test_collection", "test3")
67 assert deleted is None
70def test_get_all(database):
71 test_data1 = {"_id": "test4", "name": "Entry 1"}
72 test_data2 = {"_id": "test5", "name": "Entry 2"}
73 database.insert("test_collection", test_data1)
74 database.insert("test_collection", test_data2)
75 results = database.get_all("test_collection")
76 assert len(results) >= 2
77 database.delete_all("test_collection")
80def test_increment(database):
81 test_data = {"_id": "test6", "count": 0}
82 database.insert("test_collection", test_data)
83 database.increment("test_collection", "test6", "count", 5)
84 updated = database.get_one_by_id("test_collection", "test6")
85 assert updated["count"] == 5
86 database.delete_by_id("test_collection", "test6")
89def test_get_by_email(database):
90 test_data = {"_id": "test7", "email": "test@example.com"}
91 database.insert("test_collection", test_data)
92 result = database.get_by_email("test_collection", "test@example.com")
93 assert result is not None
94 assert result["email"] == "test@example.com"
95 database.delete_by_id("test_collection", "test7")
98def test_connection_success():
99 db = DatabaseMongoManager(
100 shared.getenv("MONGO_URI"),
101 shared.getenv("MONGO_DB_TEST", "cs3528_testing"),
102 )
103 assert db.connection is not None
104 db.close_connection()
107def test_insert_duplicate_id(database):
108 test_data = {"_id": "duplicate_test", "name": "First Entry"}
109 database.insert("test_collection", test_data)
111 with pytest.raises(DuplicateKeyError):
112 database.insert("test_collection", test_data)
114 database.delete_by_id("test_collection", "duplicate_test")
117def test_update_non_existent_record(database):
118 result = database.update_one_by_id(
119 "test_collection", "non_existent", {"name": "Updated"}
120 )
121 assert result.matched_count == 0
124def test_delete_non_existent_record(database):
125 result = database.delete_by_id("test_collection", "non_existent")
126 assert result.deleted_count == 0
129def test_get_all_empty(database):
130 results = database.get_all("empty_collection")
131 assert results == []
134def test_increment_non_existent_field(database):
135 test_data = {"_id": "increment_test"}
136 database.insert("test_collection", test_data)
138 database.increment("test_collection", "increment_test", "counter", 10)
139 updated = database.get_one_by_id("test_collection", "increment_test")
141 assert updated["counter"] == 10
143 database.delete_by_id("test_collection", "increment_test")
146def test_case_sensitivity_strict_search(database):
147 test_data = {"_id": "case_test", "email": "TEST@EXAMPLE.COM"}
148 database.insert("test_collection", test_data)
150 result = database.get_one_by_field_strict(
151 "test_collection", "email", "test@example.com"
152 )
154 assert result is not None # Should match despite case difference
155 database.delete_by_id("test_collection", "case_test")
158def test_large_data_insertion(database):
159 large_text = "A" * 16777216
160 test_data = {"_id": "large_data_test", "text": large_text}
162 with pytest.raises(Exception):
163 database.insert("test_collection", test_data)
166def test_text_search_on_non_indexed_field(database):
167 test_data = {"_id": "text_test", "description": "MongoDB text search test"}
168 database.insert("test_collection", test_data)
170 with pytest.raises(Exception):
171 database.get_all_by_text_search("test_collection", "MongoDB")
173 database.delete_by_id("test_collection", "text_test")
176def test_get_all_by_field(database):
177 """Test fetching all entries by a specific field value."""
178 database.delete_all("test_collection")
179 database.delete_collection("test_collection")
180 test_data1 = {"_id": "test8", "category": "A", "name": "Entry 1"}
181 test_data2 = {"_id": "test9", "category": "B", "name": "Entry 2"}
182 test_data3 = {"_id": "test10", "category": "A", "name": "Entry 3"}
183 database.insert("test_collection", test_data1)
184 database.insert("test_collection", test_data2)
185 database.insert("test_collection", test_data3)
187 results = database.get_all_by_field("test_collection", "category", "A")
188 assert len(results) == 2
189 assert results[0]["category"] == "A"
190 assert results[0]["name"] == "Entry 1"
191 assert results[1]["category"] == "A"
192 assert results[1]["name"] == "Entry 3"
194 database.delete_by_id("test_collection", "test8")
195 database.delete_by_id("test_collection", "test9")
196 database.delete_by_id("test_collection", "test10")
199def test_is_table(database):
200 assert database.is_table("test_collection") is False
201 database.add_table("test_collection")
202 assert database.is_table("test_collection") is True
203 assert database.is_table("non_existent_collection") is False
206def test_get_all_by_two_fields(database):
207 test_data1 = {"_id": "test10", "category": "A", "status": "active"}
208 test_data2 = {"_id": "test11", "category": "A", "status": "inactive"}
209 test_data3 = {"_id": "test12", "category": "B", "status": "active"}
210 test_data4 = {"_id": "test13", "category": "B", "status": "inactive"}
211 test_data5 = {"_id": "test14", "category": "A", "status": "active"}
212 database.insert("test_collection", test_data1)
213 database.insert("test_collection", test_data2)
214 database.insert("test_collection", test_data3)
215 database.insert("test_collection", test_data4)
216 database.insert("test_collection", test_data5)
218 results = database.get_all_by_two_fields(
219 "test_collection", "category", "A", "status", "active"
220 )
221 assert len(results) == 2
222 assert results[0]["status"] == "active"
223 assert results[1]["status"] == "active"
224 assert results[0]["_id"] == "test10"
225 assert results[1]["_id"] == "test14"
227 database.delete_by_id("test_collection", "test10")
228 database.delete_by_id("test_collection", "test11")
229 database.delete_by_id("test_collection", "test12")
230 database.delete_by_id("test_collection", "test13")
231 database.delete_by_id("test_collection", "test14")
234def test_update_by_field(database):
235 test_data = {"_id": "test15", "category": "A", "name": "Old Name"}
236 database.insert("test_collection", test_data)
237 database.update_by_field("test_collection", "category", "A", {"name": "New Name"})
239 updated = database.get_one_by_id("test_collection", "test15")
240 assert updated["name"] == "New Name"
242 database.delete_by_id("test_collection", "test15")
245def test_create_index(database):
246 result = database.create_index("test_collection", "name")
247 assert isinstance(result, str)
250def test_delete_one_by_field(database):
251 test_data = {"_id": "test20", "category": "A", "name": "Entry to delete"}
252 database.insert("test_collection", test_data)
254 database.delete_one_by_field("test_collection", "category", "A")
255 deleted = database.get_one_by_id("test_collection", "test20")
256 assert deleted is None
259def test_get_all_by_in_list(database):
260 test_data1 = {"_id": "test21", "category": "A", "name": "Entry 1"}
261 test_data2 = {"_id": "test22", "category": "B", "name": "Entry 2"}
262 test_data3 = {"_id": "test23", "category": "C", "name": "Entry 3"}
263 test_data4 = {"_id": "test24", "category": "A", "name": "Entry 4"}
265 database.insert("test_collection", test_data1)
266 database.insert("test_collection", test_data2)
267 database.insert("test_collection", test_data3)
268 database.insert("test_collection", test_data4)
270 # Fetch entries with category "A" or "C"
271 results = database.get_all_by_in_list("test_collection", "category", ["A", "C"])
273 assert len(results) == 3
274 assert any(item["_id"] == "test21" for item in results)
275 assert any(item["_id"] == "test23" for item in results)
276 assert any(item["_id"] == "test24" for item in results)
278 database.delete_by_id("test_collection", "test21")
279 database.delete_by_id("test_collection", "test22")
280 database.delete_by_id("test_collection", "test23")
281 database.delete_by_id("test_collection", "test24")
284def test_invalid_connection_string(monkeypatch):
285 """Test that an invalid connection string raises ConfigurationError."""
287 def mock_mongo_client(*args, **kwargs):
288 raise ConfigurationError("Invalid MongoDB connection string")
290 monkeypatch.setattr("pymongo.MongoClient", mock_mongo_client)
292 with pytest.raises(ConfigurationError, match="Invalid MongoDB connection string"):
293 DatabaseMongoManager("invalid_connection_string", "cs3528_testing")
296def test_operation_failure(monkeypatch):
297 """Test that an operation failure raises SystemExit."""
299 class MockClient:
300 class MockAdmin:
301 def command(self, cmd):
302 raise OperationFailure("Authentication failed")
304 def __init__(self, *args, **kwargs):
305 self.admin = self.MockAdmin()
307 monkeypatch.setattr(
308 "pymongo.MongoClient", MockClient
309 ) # Correctly patch inside pymongo
311 with pytest.raises(SystemExit) as exc_info:
312 DatabaseMongoManager("invalid_connection_string", "cs3528_testing")
314 assert exc_info.value.code == 1
317def test_server_selection_timeout(monkeypatch):
318 """Test that a server selection timeout raises SystemExit."""
320 class MockClient:
321 class MockAdmin:
322 def command(self, cmd):
323 raise ServerSelectionTimeoutError("Server selection timed out")
325 def __init__(self, *args, **kwargs):
326 self.admin = self.MockAdmin()
328 monkeypatch.setattr(
329 "pymongo.MongoClient", MockClient
330 ) # Correctly mock inside pymongo
332 with pytest.raises(SystemExit) as exc_info:
333 DatabaseMongoManager("invalid_connection_string", "cs3528_testing")
335 assert exc_info.value.code == 1
338def test_default_database_if_empty():
339 """Test that an empty database name defaults to 'cs3528_testing'."""
340 db_manager = DatabaseMongoManager(shared.getenv("MONGO_URI"), "")
341 assert db_manager.database.name == "cs3528_testing"