11from __future__ import annotations
22
3- from types import SimpleNamespace
3+ from typing import Any , cast
44from unittest .mock import AsyncMock , Mock
55from uuid import uuid4
66
77import pytest
8+ from sqlalchemy .ext .asyncio import AsyncSession
89
10+ from app .models .user import User
911from app .services import auth as auth_service
1012
1113
1214@pytest .fixture
13- def fake_session () -> object :
14- return object ( )
15+ def fake_session () -> AsyncSession :
16+ return cast ( AsyncSession , AsyncMock ( spec = AsyncSession ) )
1517
1618
1719@pytest .fixture
18- def active_user () -> SimpleNamespace :
19- return SimpleNamespace (
20- id = uuid4 (),
21- email = "user@example.com" ,
22- hashed_password = "hashed-password" ,
23- is_active = True ,
24- )
20+ def active_user () -> User :
21+ user = User ()
22+ user . id = uuid4 ()
23+ user . email = "user@example.com"
24+ user . hashed_password = "hashed-password"
25+ user . is_active = True
26+ return user
2527
2628
2729@pytest .mark .asyncio
2830async def test_register_user_raises_when_email_already_exists (
2931 monkeypatch : pytest .MonkeyPatch ,
30- fake_session : object ,
31- active_user : SimpleNamespace ,
32+ fake_session : AsyncSession ,
33+ active_user : User ,
3234) -> None :
3335 get_user_by_email = AsyncMock (return_value = active_user )
3436 create_user = AsyncMock ()
3537
36- monkeypatch .setattr (auth_service .user_repo , "get_user_by_email" , get_user_by_email )
37- monkeypatch .setattr (auth_service .user_repo , "create_user" , create_user )
38+ monkeypatch .setattr (
39+ auth_service .user_repo ,
40+ "get_user_by_email" ,
41+ cast (Any , get_user_by_email ),
42+ )
43+ monkeypatch .setattr (auth_service .user_repo , "create_user" , cast (Any , create_user ))
3844
3945 with pytest .raises (auth_service .UserAlreadyExists ):
4046 await auth_service .register_user (fake_session , "user@example.com" , "password" )
@@ -45,16 +51,20 @@ async def test_register_user_raises_when_email_already_exists(
4551@pytest .mark .asyncio
4652async def test_register_user_hashes_password_and_creates_user (
4753 monkeypatch : pytest .MonkeyPatch ,
48- fake_session : object ,
49- active_user : SimpleNamespace ,
54+ fake_session : AsyncSession ,
55+ active_user : User ,
5056) -> None :
5157 get_user_by_email = AsyncMock (return_value = None )
5258 hash_password = AsyncMock (return_value = "hashed-by-test" )
5359 create_user = AsyncMock (return_value = active_user )
5460
55- monkeypatch .setattr (auth_service .user_repo , "get_user_by_email" , get_user_by_email )
56- monkeypatch .setattr (auth_service , "hash_password" , hash_password )
57- monkeypatch .setattr (auth_service .user_repo , "create_user" , create_user )
61+ monkeypatch .setattr (
62+ auth_service .user_repo ,
63+ "get_user_by_email" ,
64+ cast (Any , get_user_by_email ),
65+ )
66+ monkeypatch .setattr (auth_service , "hash_password" , cast (Any , hash_password ))
67+ monkeypatch .setattr (auth_service .user_repo , "create_user" , cast (Any , create_user ))
5868
5969 created = await auth_service .register_user (
6070 fake_session ,
@@ -74,15 +84,19 @@ async def test_register_user_hashes_password_and_creates_user(
7484@pytest .mark .asyncio
7585async def test_authenticate_user_uses_dummy_hash_when_user_not_found (
7686 monkeypatch : pytest .MonkeyPatch ,
77- fake_session : object ,
87+ fake_session : AsyncSession ,
7888) -> None :
7989 get_user_by_email = AsyncMock (return_value = None )
8090 get_dummy_hash = Mock (return_value = "dummy-hash" )
8191 verify_password = AsyncMock (return_value = False )
8292
83- monkeypatch .setattr (auth_service .user_repo , "get_user_by_email" , get_user_by_email )
84- monkeypatch .setattr (auth_service , "get_dummy_hash" , get_dummy_hash )
85- monkeypatch .setattr (auth_service , "verify_password" , verify_password )
93+ monkeypatch .setattr (
94+ auth_service .user_repo ,
95+ "get_user_by_email" ,
96+ cast (Any , get_user_by_email ),
97+ )
98+ monkeypatch .setattr (auth_service , "get_dummy_hash" , cast (Any , get_dummy_hash ))
99+ monkeypatch .setattr (auth_service , "verify_password" , cast (Any , verify_password ))
86100
87101 authenticated = await auth_service .authenticate_user (
88102 fake_session ,
@@ -100,15 +114,20 @@ async def test_authenticate_user_uses_dummy_hash_when_user_not_found(
100114@pytest .mark .asyncio
101115async def test_authenticate_active_user_raises_for_inactive_user (
102116 monkeypatch : pytest .MonkeyPatch ,
117+ fake_session : AsyncSession ,
103118) -> None :
104- inactive_user = SimpleNamespace (is_active = False )
119+ inactive_user = User ()
120+ inactive_user .id = uuid4 ()
121+ inactive_user .email = "inactive@example.com"
122+ inactive_user .hashed_password = "hashed-password"
123+ inactive_user .is_active = False
105124 authenticate_user = AsyncMock (return_value = inactive_user )
106125
107- monkeypatch .setattr (auth_service , "authenticate_user" , authenticate_user )
126+ monkeypatch .setattr (auth_service , "authenticate_user" , cast ( Any , authenticate_user ) )
108127
109128 with pytest .raises (auth_service .UserInactive ):
110129 await auth_service .authenticate_active_user (
111- object () ,
130+ fake_session ,
112131 "user@example.com" ,
113132 "password" ,
114133 )
@@ -117,10 +136,12 @@ async def test_authenticate_active_user_raises_for_inactive_user(
117136@pytest .mark .asyncio
118137async def test_validate_refresh_subject_raises_when_user_not_found (
119138 monkeypatch : pytest .MonkeyPatch ,
120- fake_session : object ,
139+ fake_session : AsyncSession ,
121140) -> None :
122141 get_user_by_id = AsyncMock (return_value = None )
123- monkeypatch .setattr (auth_service .user_repo , "get_user_by_id" , get_user_by_id )
142+ monkeypatch .setattr (
143+ auth_service .user_repo , "get_user_by_id" , cast (Any , get_user_by_id )
144+ )
124145
125146 with pytest .raises (auth_service .UserNotFound ):
126147 await auth_service .validate_refresh_subject (fake_session , uuid4 ())
@@ -129,11 +150,17 @@ async def test_validate_refresh_subject_raises_when_user_not_found(
129150@pytest .mark .asyncio
130151async def test_validate_refresh_subject_raises_when_user_inactive (
131152 monkeypatch : pytest .MonkeyPatch ,
132- fake_session : object ,
153+ fake_session : AsyncSession ,
133154) -> None :
134- inactive_user = SimpleNamespace (is_active = False )
155+ inactive_user = User ()
156+ inactive_user .id = uuid4 ()
157+ inactive_user .email = "inactive@example.com"
158+ inactive_user .hashed_password = "hashed-password"
159+ inactive_user .is_active = False
135160 get_user_by_id = AsyncMock (return_value = inactive_user )
136- monkeypatch .setattr (auth_service .user_repo , "get_user_by_id" , get_user_by_id )
161+ monkeypatch .setattr (
162+ auth_service .user_repo , "get_user_by_id" , cast (Any , get_user_by_id )
163+ )
137164
138165 with pytest .raises (auth_service .UserInactive ):
139166 await auth_service .validate_refresh_subject (fake_session , uuid4 ())
0 commit comments