11from unittest .mock import AsyncMock , patch
22
33import pytest
4- from fastapi .testclient import TestClient
54from jwt .exceptions import ExpiredSignatureError , InvalidTokenError
65
7- from app .main import app
86from app .models .auth import User
97
108
119@pytest .fixture (scope = "session" , autouse = True )
1210def 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