Skip to content

Commit 3a203e3

Browse files
committed
test: update tests to work with the new DI in db manager
1 parent e5bf6f3 commit 3a203e3

File tree

3 files changed

+139
-123
lines changed

3 files changed

+139
-123
lines changed

tests/conftest.py

Lines changed: 53 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,68 @@
1-
from unittest.mock import AsyncMock, MagicMock, patch
1+
from contextlib import asynccontextmanager
2+
from unittest.mock import AsyncMock, MagicMock
23

34
import pytest
45
from fastapi.testclient import TestClient
56

6-
_mock_db_manager_patch = patch("app.database.DatabaseManager")
7+
from app.controllers.auth_controller import get_auth_service
8+
from app.database import get_database_manager
79

8-
_mock_db_manager_class = _mock_db_manager_patch.start()
9-
_mock_db_manager = MagicMock()
10-
_mock_db_manager_class.return_value = _mock_db_manager
1110

12-
_mock_db_manager.get_odmantic_engine.return_value = AsyncMock()
13-
_mock_db_manager.get_neo4j_driver.return_value = MagicMock()
14-
_mock_db_manager.initialize = AsyncMock()
15-
_mock_db_manager.close = AsyncMock()
11+
@pytest.fixture(scope="session")
12+
def mock_db_manager():
13+
mock_db = MagicMock()
1614

15+
mock_engine = AsyncMock()
16+
mock_db.get_odmantic_engine.return_value = mock_engine
1717

18-
def pytest_sessionfinish(session, exitstatus):
19-
_mock_db_manager_patch.stop()
18+
mock_driver = MagicMock()
19+
mock_session = AsyncMock()
20+
mock_driver.session.return_value.__aenter__.return_value = mock_session
21+
mock_db.get_neo4j_driver.return_value = mock_driver
2022

23+
mock_db.initialize = AsyncMock()
24+
mock_db.close = AsyncMock()
2125

22-
@pytest.fixture(autouse=True)
23-
def reset_auth_service_singleton():
24-
yield
26+
return mock_db
2527

2628

27-
@pytest.fixture(scope="module")
28-
def client():
29+
@pytest.fixture(scope="session")
30+
def mock_auth_service():
31+
mock_auth = MagicMock()
32+
mock_auth.read_user_by_email = AsyncMock()
33+
mock_auth.create_user = AsyncMock()
34+
mock_auth.create_revoked_token = AsyncMock()
35+
mock_auth.update_user_password = AsyncMock()
36+
mock_auth.is_token_revoked = AsyncMock()
37+
return mock_auth
38+
39+
40+
@pytest.fixture(scope="session")
41+
def mock_jwt_bearer():
42+
class MockJWTBearer:
43+
async def __call__(self, request):
44+
return {"user_id": "abc123"}
45+
46+
return MockJWTBearer()
47+
48+
49+
@pytest.fixture(scope="function")
50+
def client(mock_db_manager, mock_auth_service, mock_jwt_bearer):
51+
from app.controllers.auth_controller import jwt_bearer
2952
from app.main import app
53+
54+
@asynccontextmanager
55+
async def test_lifespan(app):
56+
yield
57+
58+
app.router.lifespan_context = test_lifespan
59+
60+
app.dependency_overrides[get_database_manager] = lambda: mock_db_manager
61+
app.dependency_overrides[get_auth_service] = lambda: mock_auth_service
62+
app.dependency_overrides[jwt_bearer] = lambda: mock_jwt_bearer
63+
3064
with TestClient(app) as c:
3165
yield c
66+
67+
app.dependency_overrides.clear()
68+
Lines changed: 61 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,21 @@
11
from unittest.mock import AsyncMock, patch
22

33
import pytest
4-
from fastapi.testclient import TestClient
54
from jwt.exceptions import ExpiredSignatureError, InvalidTokenError
65

7-
from app.main import app
86
from app.models.auth import User
97

108

119
@pytest.fixture(scope="session", autouse=True)
1210
def patch_jwt():
13-
with patch("app.utils.jwt_encoder.JWTBearer.__call__", new=AsyncMock(return_value={"user_id": "abc123"})):
11+
with patch("app.controllers.auth_controller.jwt_bearer.__call__", new=AsyncMock(return_value={"user_id": "abc123"})):
1412
yield
1513

16-
@pytest.fixture(autouse=True)
17-
def mock_services():
18-
with patch("app.controllers.auth_controller.auth_service") as mock_auth:
19-
20-
mock_auth.read_user_by_email = AsyncMock()
21-
mock_auth.create_user = AsyncMock()
22-
mock_auth.validate_password = AsyncMock()
23-
mock_auth.change_password = AsyncMock()
24-
mock_auth.revoke_token = AsyncMock()
25-
mock_auth.is_token_revoked = AsyncMock()
26-
mock_auth.create_revoked_token = AsyncMock()
27-
mock_auth.update_user_password = AsyncMock()
28-
29-
yield mock_auth
30-
31-
mock_auth.reset_mock()
32-
33-
client = TestClient(app)
34-
3514

3615
# --- SIGNUP ---
37-
def test_signup_success(mock_services):
38-
mock_auth = mock_services
39-
mock_auth.read_user_by_email.return_value = None
40-
mock_auth.create_user.return_value = None
16+
def test_signup_success(client, mock_auth_service):
17+
mock_auth_service.read_user_by_email.return_value = None
18+
mock_auth_service.create_user.return_value = None
4119

4220
response = client.post("/signup", json={
4321
"email": "test@example.com",
@@ -47,9 +25,8 @@ def test_signup_success(mock_services):
4725
assert response.json()["detail"] == "signup_success"
4826

4927

50-
def test_signup_user_exists(mock_services):
51-
mock_auth = mock_services
52-
mock_auth.read_user_by_email.return_value = {"email": "test@example.com"}
28+
def test_signup_user_exists(client, mock_auth_service):
29+
mock_auth_service.read_user_by_email.return_value = {"email": "test@example.com"}
5330

5431
response = client.post("/signup", json={"email": "test@example.com", "password": "13pAssword*"})
5532
assert response.status_code == 409
@@ -62,48 +39,43 @@ def test_signup_user_exists(mock_services):
6239
("weAkkaew", 422, "Value error, the password must contain at least one digit"),
6340
("1weAkkaew", 422, "Value error, the password must contain at least one special character")
6441
])
65-
def test_signup_fails_with_weak_password(mock_services, password, status_code, error_message):
66-
mock_auth = mock_services
67-
mock_auth.read_user_by_email.return_value = None
68-
mock_auth.create_user.return_value = None
42+
def test_signup_fails_with_weak_password(client, mock_auth_service, password, status_code, error_message):
43+
mock_auth_service.read_user_by_email.return_value = None
44+
mock_auth_service.create_user.return_value = None
6945

7046
response = client.post("/signup", json={"email": "test@example.com", "password": password})
7147
assert response.status_code == status_code
7248
assert response.json()["detail"] == "validation_error"
7349

7450

75-
def test_signup_wrong_email(mock_services):
76-
mock_auth = mock_services
77-
mock_auth.read_user_by_email.return_value = None
51+
def test_signup_wrong_email(client, mock_auth_service):
52+
mock_auth_service.read_user_by_email.return_value = None
7853

7954
response = client.post("/signup", json={"email": "some_text", "password": "13pAssword*"})
8055
assert response.status_code == 422
8156
assert response.json()["detail"] == "validation_error"
8257

8358

8459
# --- LOGIN ---
85-
def test_login_user_not_exist(mock_services):
86-
mock_auth = mock_services
87-
mock_auth.read_user_by_email.return_value = None
60+
def test_login_user_not_exist(client, mock_auth_service):
61+
mock_auth_service.read_user_by_email.return_value = None
8862

8963
response = client.post("/login", json={"email": "nouser@example.com", "password": "13pAssword*"})
9064
assert response.status_code == 400
9165
assert response.json()["detail"] == "user_no_exist"
9266

9367

94-
def test_login_wrong_password(mock_services):
95-
mock_auth = mock_services
96-
mock_auth.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
68+
def test_login_wrong_password(client, mock_auth_service):
69+
mock_auth_service.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
9770

9871
with patch("app.controllers.auth_controller.password_encoder.verify", new=AsyncMock(return_value=False)):
9972
response = client.post("/login", json={"email": "test@example.com", "password": "15pAssword*"})
10073
assert response.status_code == 400
10174
assert response.json()["detail"] == "user_incorrect_password"
10275

10376

104-
def test_login_success(mock_services):
105-
mock_auth = mock_services
106-
mock_auth.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
77+
def test_login_success(client, mock_auth_service):
78+
mock_auth_service.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
10779

10880
with patch("app.controllers.auth_controller.password_encoder.verify", new=AsyncMock(return_value=True)), \
10981
patch("app.controllers.auth_controller.jwt_bearer.create_access_token", new=AsyncMock(return_value="access")), \
@@ -116,41 +88,40 @@ def test_login_success(mock_services):
11688

11789

11890
# --- LOGOUT ---
119-
def test_logout_no_refresh_token(mock_services):
91+
def test_logout_no_refresh_token(client, mock_auth_service):
92+
headers = {"Authorization": "Bearer faketoken"}
12093
client.cookies.clear()
12194
client.cookies.set("access_token", "faketoken")
122-
response = client.post("/logout")
95+
response = client.post("/logout", headers=headers)
12396
assert response.status_code == 400
12497
assert response.json()["detail"] == "missing_refresh_token"
12598

12699

127-
def test_logout_success(mock_services):
128-
mock_auth = mock_services
129-
mock_auth.create_revoked_token.return_value = None
100+
def test_logout_success(client, mock_auth_service):
101+
mock_auth_service.create_revoked_token.return_value = None
130102

131103
with patch("app.controllers.auth_controller.jwt_bearer.read_expiration_date", new=AsyncMock(return_value=123456)):
104+
headers = {"Authorization": "Bearer faketoken"}
132105
client.cookies.clear()
133106
client.cookies.set("access_token", "faketoken")
134107
client.cookies.set("refresh_token", "refresh")
135-
response = client.post("/logout")
108+
response = client.post("/logout", headers=headers)
136109
assert response.status_code == 200
137110
assert response.json()["detail"] == "logout_success"
138111

139112

140113
# --- ACCOUNT EXISTS ---
141-
def test_account_exists_true(mock_services):
142-
mock_auth = mock_services
143-
mock_auth.read_user_by_email.return_value = {"email": "test@example.com"}
114+
def test_account_exists_true(client, mock_auth_service):
115+
mock_auth_service.read_user_by_email.return_value = {"email": "test@example.com"}
144116

145117
response = client.post("/account_exists", json={"email": "test@example.com"})
146118
assert response.status_code == 200
147119
assert response.json()["user_exists"] is True
148120
assert response.json()["detail"] == "account_exists_success"
149121

150122

151-
def test_account_exists_false(mock_services):
152-
mock_auth = mock_services
153-
mock_auth.read_user_by_email.return_value = None
123+
def test_account_exists_false(client, mock_auth_service):
124+
mock_auth_service.read_user_by_email.return_value = None
154125

155126
response = client.post("/account_exists", json={"email": "nouser@example.com"})
156127
assert response.status_code == 200
@@ -159,52 +130,52 @@ def test_account_exists_false(mock_services):
159130

160131

161132
# --- CHANGE PASSWORD ---
162-
def test_change_password_user_not_exist(mock_services):
163-
mock_auth = mock_services
164-
mock_auth.read_user_by_email.return_value = None
133+
def test_change_password_user_not_exist(client, mock_auth_service):
134+
mock_auth_service.read_user_by_email.return_value = None
165135

136+
headers = {"Authorization": "Bearer faketoken"}
166137
client.cookies.clear()
167138
client.cookies.set("access_token", "faketoken")
168-
response = client.post("/change_password", json={"email": "nouser@example.com", "old_password": "13pAssword*", "new_password": "14pAssword*"})
139+
response = client.post("/change_password", json={"email": "nouser@example.com", "old_password": "13pAssword*", "new_password": "14pAssword*"}, headers=headers)
169140
assert response.status_code == 400
170141
assert response.json()["detail"] == "user_no_exist"
171142

172143

173-
def test_change_password_invalid_old_password(mock_services):
174-
mock_auth = mock_services
175-
mock_auth.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
144+
def test_change_password_invalid_old_password(client, mock_auth_service):
145+
mock_auth_service.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
176146

177147
with patch("app.controllers.auth_controller.password_encoder.verify", new=AsyncMock(return_value=False)):
148+
headers = {"Authorization": "Bearer faketoken"}
178149
client.cookies.clear()
179150
client.cookies.set("access_token", "faketoken")
180-
response = client.post("/change_password", json={"email": "test@example.com", "old_password": "15pAssword*", "new_password": "14pAssword*"})
151+
response = client.post("/change_password", json={"email": "test@example.com", "old_password": "15pAssword*", "new_password": "14pAssword*"}, headers=headers)
181152
assert response.status_code == 400
182153
assert response.json()["detail"] == "user_invalid_old_password"
183154

184155

185-
def test_change_password_success(mock_services):
186-
mock_auth = mock_services
187-
mock_auth.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
188-
mock_auth.update_user_password.return_value = None
156+
def test_change_password_success(client, mock_auth_service):
157+
mock_auth_service.read_user_by_email.return_value = User(email="test@example.com", password="hashed")
158+
mock_auth_service.update_user_password.return_value = None
189159

190160
with patch("app.controllers.auth_controller.password_encoder.verify", new=AsyncMock(return_value=True)), \
191161
patch("app.controllers.auth_controller.password_encoder.hash", new=AsyncMock(return_value="new_hashed")):
162+
headers = {"Authorization": "Bearer faketoken"}
192163
client.cookies.clear()
193164
client.cookies.set("access_token", "faketoken")
194-
response = client.post("/change_password", json={"email": "test@example.com", "old_password": "13pAssword*", "new_password": "14pAssword*"})
165+
response = client.post("/change_password", json={"email": "test@example.com", "old_password": "13pAssword*", "new_password": "14pAssword*"}, headers=headers)
195166
assert response.status_code == 200
196167
assert response.json()["detail"] == "change_password_success"
197168

198169

199170
# --- CHECK TOKEN ---
200-
def test_check_token_missing():
171+
def test_check_token_missing(client):
201172
headers = {"Authorization": "Bearer faketoken"}
202173
response = client.post("/check_token", json={"token": ""}, headers=headers)
203174
assert response.status_code == 400
204175
assert response.json()["detail"] == "token_missing"
205176

206177

207-
def test_check_token_valid():
178+
def test_check_token_valid(client):
208179
headers = {"Authorization": "Bearer faketoken"}
209180
with patch("app.controllers.auth_controller.jwt_bearer.verify_access_token", new=AsyncMock(return_value={"user_id": "abc123"})):
210181
response = client.post("/check_token", json={"token": "sometoken"}, headers=headers)
@@ -213,15 +184,15 @@ def test_check_token_valid():
213184
assert response.json()["detail"] == "token_verification_success"
214185

215186

216-
def test_check_token_expired():
187+
def test_check_token_expired(client):
217188
headers = {"Authorization": "Bearer faketoken"}
218189
with patch("app.controllers.auth_controller.jwt_bearer.verify_access_token", new=AsyncMock(side_effect=ExpiredSignatureError)):
219190
response = client.post("/check_token", json={"token": "expiredtoken"}, headers=headers)
220191
assert response.status_code == 401
221192
assert response.json()["detail"] == "token_expired"
222193

223194

224-
def test_check_token_invalid():
195+
def test_check_token_invalid(client):
225196
headers = {"Authorization": "Bearer faketoken"}
226197
with patch("app.controllers.auth_controller.jwt_bearer.verify_access_token", new=AsyncMock(side_effect=InvalidTokenError)):
227198
response = client.post("/check_token", json={"token": "invalidtoken"}, headers=headers)
@@ -230,33 +201,29 @@ def test_check_token_invalid():
230201

231202

232203
# --- REFRESH TOKEN ---
233-
def test_refresh_token_missing(mock_services):
204+
def test_refresh_token_missing(client, mock_auth_service):
234205
headers = {"Authorization": "Bearer faketoken"}
235206
response = client.post("/refresh_token", headers=headers)
236207
assert response.status_code == 400
237208
assert response.json()["detail"] == "missing_refresh_token"
238209

239210

240-
def test_refresh_token_revoked(mock_services):
241-
mock_auth = mock_services
242-
mock_auth.is_token_revoked.return_value = True
211+
def test_refresh_token_revoked(client, mock_auth_service):
212+
mock_auth_service.is_token_revoked.return_value = True
243213

244-
with TestClient(app) as test_client:
245-
test_client.cookies.set("refresh_token", "revokedtoken")
246-
response = test_client.post("/refresh_token")
247-
assert response.status_code == 401
248-
assert response.json()["detail"] == "token_revoked"
214+
client.cookies.set("refresh_token", "revokedtoken")
215+
response = client.post("/refresh_token")
216+
assert response.status_code == 401
217+
assert response.json()["detail"] == "token_revoked"
249218

250219

251-
def test_refresh_token_success(mock_services):
252-
mock_auth = mock_services
253-
mock_auth.is_token_revoked.return_value = False
220+
def test_refresh_token_success(client, mock_auth_service):
221+
mock_auth_service.is_token_revoked.return_value = False
254222

255-
with TestClient(app) as test_client:
256-
test_client.cookies.set("refresh_token", "validtoken")
257-
with patch("app.controllers.auth_controller.jwt_bearer.verify_refresh_token", new=AsyncMock(return_value={"user_id": "1"})), \
258-
patch("app.controllers.auth_controller.jwt_bearer.create_access_token", new=AsyncMock(return_value="new_access")):
259-
response = test_client.post("/refresh_token")
260-
print(response.json())
261-
assert response.status_code == 200
262-
assert response.json()["detail"] == "refresh_token_success"
223+
client.cookies.set("refresh_token", "validtoken")
224+
with patch("app.controllers.auth_controller.jwt_bearer.verify_refresh_token", new=AsyncMock(return_value={"user_id": "1"})), \
225+
patch("app.controllers.auth_controller.jwt_bearer.create_access_token", new=AsyncMock(return_value="new_access")):
226+
response = client.post("/refresh_token")
227+
print(response.json())
228+
assert response.status_code == 200
229+
assert response.json()["detail"] == "refresh_token_success"

0 commit comments

Comments
 (0)