Skip to content

Commit 369b47a

Browse files
authored
Merge pull request #44 from ClassConnect-org/tests
Add: Test for db delete
2 parents 6db35f6 + 70a968e commit 369b47a

1 file changed

Lines changed: 69 additions & 76 deletions

File tree

tests/unit/test_db_delete.py

Lines changed: 69 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,35 @@
22
from unittest.mock import MagicMock
33

44
import pytest
5+
from fastapi import HTTPException
56
from fastapi.responses import Response
67

7-
# Adjust import to real path
88
from app.db.connector import DB
99

1010

11-
# Fake connection and pool classes as per provided tests
11+
class DummyPool:
12+
def __init__(self, conn=None, error=None):
13+
self._conn = conn
14+
self._error = error
15+
self.got = False
16+
self.put_back = False
17+
18+
def getconn(self):
19+
self.got = True
20+
if self._error:
21+
raise self._error
22+
return self._conn
23+
24+
def putconn(self, conn):
25+
self.put_back = True
26+
27+
28+
# Fake connection and pool classes
1229
class FakeConn:
13-
def __init__(self):
30+
def __init__(self, rowcount=1):
1431
self.cursor_obj = MagicMock()
32+
# simulate cursor().rowcount attribute
33+
self.cursor_obj.rowcount = rowcount
1534

1635
def cursor(self):
1736
return self.cursor_obj
@@ -25,7 +44,6 @@ def close(self):
2544

2645
class FakePool:
2746
def __init__(self, minconn, maxconn, dsn):
28-
# can assert on minconn, maxconn, dsn if desired
2947
self._conn = FakeConn()
3048
self.getconn = MagicMock(return_value=self._conn)
3149
self.putconn = MagicMock()
@@ -34,91 +52,66 @@ def __init__(self, minconn, maxconn, dsn):
3452

3553
@pytest.fixture(autouse=True)
3654
def fake_pool(monkeypatch):
37-
# Patch environment and pool initializer
55+
# Patch the SimpleConnectionPool to return our FakePool
3856
monkeypatch.setenv("DATABASE_URL", "postgres://fake")
3957
monkeypatch.setattr(
4058
"app.db.connector.pool.SimpleConnectionPool",
4159
lambda minconn, maxconn, dsn: FakePool(minconn, maxconn, dsn),
4260
)
43-
# Reset singleton
61+
# Reset singleton instance
4462
DB._instance = None
4563
yield
4664

4765

48-
def test_create_table_and_store_chat():
49-
# Instantiate DB so __init__ runs create_table
50-
db = DB(minconn=2, maxconn=5)
51-
fake_pool = db.pool
52-
conn = fake_pool.getconn()
53-
# Check that DDL for chats table was executed
54-
expected_ddl = """
55-
CREATE TABLE IF NOT EXISTS chats (
56-
uid UUID PRIMARY KEY,
57-
question TEXT NOT NULL,
58-
answer TEXT NOT NULL,
59-
votes INTEGER DEFAULT 0,
60-
comment TEXT,
61-
user_id UUID
62-
);
63-
"""
64-
conn.cursor_obj.execute.assert_any_call(expected_ddl)
65-
# putconn called for initialization
66-
fake_pool.putconn.assert_called_with(conn)
67-
68-
# Now test store_chat
69-
fake_pool.getconn.reset_mock()
70-
fake_pool.putconn.reset_mock()
71-
conn.cursor_obj.reset_mock()
72-
73-
test_uid = str(uuid.uuid4())
74-
test_user = uuid.uuid4()
75-
db.store_chat("¿Hola?", "¡Hola!", test_uid, test_user)
76-
77-
# Verify INSERT called with correct SQL and params
78-
conn.cursor_obj.execute.assert_called_once_with(
79-
"""
80-
INSERT into chats (uid, question, answer, votes, user_id) values (%s, %s, %s, %s, %s);
81-
""",
82-
(test_uid, "¿Hola?", "¡Hola!", 0, str(test_user)),
83-
)
84-
fake_pool.putconn.assert_called_with(conn)
66+
@pytest.fixture(autouse=True)
67+
def setup_pool(monkeypatch):
68+
# Prepare a DummyPool and assign to DB instances
69+
pool = DummyPool()
70+
# Patch DB class to use our pool
71+
yield pool
8572

8673

87-
def test_change_votes_success_up():
88-
db = DB()
89-
# Prepare inputs
90-
chat_id = "11111111-1111-1111-1111-111111111111"
91-
user_id = uuid.UUID(int=0)
92-
# Call change_votes to upvote
93-
response = db.change_votes(
94-
chat_id=chat_id,
95-
up=True,
96-
down=False,
97-
equal=False,
98-
user_id=user_id,
99-
comment="Comentario",
100-
)
74+
def test_delete_chat_success():
75+
db = DB(minconn=1, maxconn=1)
76+
conn = db.pool.getconn()
77+
# Ensure rowcount > 0
78+
conn.cursor_obj.rowcount = 1
10179

80+
response = db.delete_chat(str(uuid.uuid4()))
81+
# Should return 204 response
10282
assert isinstance(response, Response)
10383
assert response.status_code == 204
84+
# Verify DELETE executed
85+
sql, params = conn.cursor_obj.execute.call_args[0]
86+
assert "DELETE FROM chats" in sql
87+
# Connection returned to pool
88+
assert db.pool.putconn.called
10489

105-
# Inspect cursor calls
106-
fake_conn = db.pool.getconn()
107-
fake_cursor = fake_conn.cursor_obj
108-
calls = fake_cursor.execute.call_args_list
109-
assert calls, "cursor.execute was not called"
110-
111-
expected_params = (
112-
1,
113-
"Comentario",
114-
chat_id,
115-
str(user_id),
116-
)
117-
# Find call with UPDATE chats and expected params
118-
found = any(
119-
"UPDATE chats" in call.args[0] and call.args[1] == expected_params
120-
for call in calls
121-
)
122-
assert found, f"No UPDATE chats call with params {expected_params}, calls: {calls}"
123-
# Ensure connection returned
90+
91+
def test_delete_chat_not_found():
92+
db = DB(minconn=1, maxconn=1)
93+
conn = db.pool.getconn()
94+
# Simulate no rows deleted
95+
conn.cursor_obj.rowcount = 0
96+
97+
with pytest.raises(HTTPException) as exc:
98+
db.delete_chat(str(uuid.uuid4()))
99+
assert exc.value.status_code == 404
100+
assert "not found" in exc.value.detail.lower()
101+
# Connection returned
124102
assert db.pool.putconn.called
103+
104+
105+
def test_delete_chat_db_error(setup_pool):
106+
# Simulate generic exception during getconn
107+
setup_pool._conn = None
108+
setup_pool._error = Exception("DB down")
109+
110+
db = DB()
111+
result = db.delete_chat("any-id")
112+
# On generic exception, should return a 204 Response
113+
assert isinstance(result, Response), "Expected a Response on generic error"
114+
assert result.status_code == 204, "Expected status code 204"
115+
# pool.getconn was attempted
116+
# No putconn since conn was never established
117+
assert not setup_pool.put_back, "Did not expect pool.putconn when getconn fails"

0 commit comments

Comments
 (0)