Skip to content

Commit 75bfdc5

Browse files
committed
Implement tests
1 parent 2ab49e1 commit 75bfdc5

File tree

4 files changed

+157
-176
lines changed

4 files changed

+157
-176
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies = [
3535
"httpx",
3636
"asgi_lifespan",
3737
"ruff",
38+
"moto[all]",
3839
]
3940

4041
[tool.hatch.envs.default.scripts]

tests/conftest.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
import os
1+
import uuid
22
from typing import Any, Optional
33

44
import pytest
55
from fastapi_users import schemas
66

7-
DATABASE_URL = os.getenv(
8-
"DATABASE_URL", "sqlite+aiosqlite:///./test-sqlalchemy-user.db"
9-
)
10-
117

128
class User(schemas.BaseUser):
139
first_name: Optional[str]
@@ -45,3 +41,8 @@ def oauth_account2() -> dict[str, Any]:
4541
"account_id": "user_oauth2",
4642
"account_email": "king.arthur@camelot.bt",
4743
}
44+
45+
46+
@pytest.fixture
47+
def user_id() -> uuid.UUID:
48+
return uuid.uuid4()

tests/test_access_token.py

Lines changed: 61 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,130 +2,120 @@
22
from collections.abc import AsyncGenerator
33
from datetime import datetime, timedelta, timezone
44

5+
import aioboto3
56
import pytest
67
import pytest_asyncio
8+
from moto import mock_aws
79
from pydantic import UUID4
8-
from sqlalchemy import exc
9-
from sqlalchemy.ext.asyncio import (
10-
AsyncEngine,
11-
AsyncSession,
12-
async_sessionmaker,
13-
create_async_engine,
14-
)
15-
from sqlalchemy.orm import DeclarativeBase
1610

17-
from fastapi_users_db_sqlalchemy import SQLAlchemyBaseUserTableUUID
18-
from fastapi_users_db_sqlalchemy.access_token import (
19-
SQLAlchemyAccessTokenDatabase,
20-
SQLAlchemyBaseAccessTokenTableUUID,
11+
from fastapi_users_db_dynamodb import DynamoDBBaseUserTableUUID, DynamoDBUserDatabase
12+
from fastapi_users_db_dynamodb.access_token import (
13+
DynamoDBAccessTokenDatabase,
14+
DynamoDBBaseAccessTokenTableUUID,
2115
)
22-
from tests.conftest import DATABASE_URL
2316

2417

25-
class Base(DeclarativeBase):
18+
class Base:
2619
pass
2720

2821

29-
class AccessToken(SQLAlchemyBaseAccessTokenTableUUID, Base):
22+
class AccessToken(DynamoDBBaseAccessTokenTableUUID, Base):
3023
pass
3124

3225

33-
class User(SQLAlchemyBaseUserTableUUID, Base):
26+
class User(DynamoDBBaseUserTableUUID, Base):
3427
pass
3528

3629

37-
def create_async_session_maker(engine: AsyncEngine):
38-
return async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
39-
40-
4130
@pytest.fixture
4231
def user_id() -> UUID4:
4332
return uuid.uuid4()
4433

4534

4635
@pytest_asyncio.fixture
47-
async def sqlalchemy_access_token_db(
36+
async def dynamodb_access_token_db(
4837
user_id: UUID4,
49-
) -> AsyncGenerator[SQLAlchemyAccessTokenDatabase[AccessToken], None]:
50-
engine = create_async_engine(DATABASE_URL)
51-
sessionmaker = create_async_session_maker(engine)
38+
) -> AsyncGenerator[DynamoDBAccessTokenDatabase[AccessToken]]:
39+
with mock_aws():
40+
session = aioboto3.Session()
41+
user_table_name = "users_test"
42+
token_table_name = "access_tokens_test"
43+
44+
user_db = DynamoDBUserDatabase(
45+
session, DynamoDBBaseUserTableUUID, user_table_name
46+
)
47+
user = await user_db.create(
48+
{
49+
"id": user_id,
50+
"email": "lancelot@camelot.bt",
51+
"hashed_password": "guinevere",
52+
}
53+
)
5254

53-
async with engine.begin() as connection:
54-
await connection.run_sync(Base.metadata.create_all)
55+
token_db = DynamoDBAccessTokenDatabase(session, AccessToken, token_table_name)
5556

56-
async with sessionmaker() as session:
57-
user = User(
58-
id=user_id, email="lancelot@camelot.bt", hashed_password="guinevere"
59-
)
60-
session.add(user)
61-
await session.commit()
57+
# Vorherigen Token löschen, falls er existiert
58+
token_obj = await token_db.get_by_token("TOKEN")
59+
if token_obj:
60+
await token_db.delete(token_obj)
6261

63-
yield SQLAlchemyAccessTokenDatabase(session, AccessToken)
62+
yield token_db
6463

65-
async with engine.begin() as connection:
66-
await connection.run_sync(Base.metadata.drop_all)
64+
token_obj = await token_db.get_by_token("TOKEN")
65+
if token_obj:
66+
await token_db.delete(token_obj)
67+
68+
await user_db.delete(user)
6769

6870

6971
@pytest.mark.asyncio
7072
async def test_queries(
71-
sqlalchemy_access_token_db: SQLAlchemyAccessTokenDatabase[AccessToken],
73+
dynamodb_access_token_db: DynamoDBAccessTokenDatabase[AccessToken],
7274
user_id: UUID4,
7375
):
7476
access_token_create = {"token": "TOKEN", "user_id": user_id}
7577

76-
# Create
77-
access_token = await sqlalchemy_access_token_db.create(access_token_create)
78+
access_token = await dynamodb_access_token_db.create(access_token_create)
7879
assert access_token.token == "TOKEN"
7980
assert access_token.user_id == user_id
8081

81-
# Update
82-
update_dict = {"created_at": datetime.now(timezone.utc)}
83-
updated_access_token = await sqlalchemy_access_token_db.update(
84-
access_token, update_dict
82+
new_time = datetime.now(timezone.utc)
83+
updated_access_token = await dynamodb_access_token_db.update(
84+
access_token, {"created_at": new_time}
8585
)
86-
assert updated_access_token.created_at.replace(microsecond=0) == update_dict[
87-
"created_at"
88-
].replace(microsecond=0)
89-
90-
# Get by token
91-
access_token_by_token = await sqlalchemy_access_token_db.get_by_token(
92-
access_token.token
86+
assert updated_access_token.created_at.replace(microsecond=0) == new_time.replace(
87+
microsecond=0
9388
)
94-
assert access_token_by_token is not None
9589

96-
# Get by token expired
97-
access_token_by_token = await sqlalchemy_access_token_db.get_by_token(
90+
token_obj = await dynamodb_access_token_db.get_by_token(access_token.token)
91+
assert token_obj is not None
92+
93+
token_obj = await dynamodb_access_token_db.get_by_token(
9894
access_token.token, max_age=datetime.now(timezone.utc) + timedelta(hours=1)
9995
)
100-
assert access_token_by_token is None
96+
assert token_obj is None
10197

102-
# Get by token not expired
103-
access_token_by_token = await sqlalchemy_access_token_db.get_by_token(
98+
token_obj = await dynamodb_access_token_db.get_by_token(
10499
access_token.token, max_age=datetime.now(timezone.utc) - timedelta(hours=1)
105100
)
106-
assert access_token_by_token is not None
101+
assert token_obj is not None
107102

108-
# Get by token unknown
109-
access_token_by_token = await sqlalchemy_access_token_db.get_by_token(
110-
"NOT_EXISTING_TOKEN"
111-
)
112-
assert access_token_by_token is None
103+
token_obj = await dynamodb_access_token_db.get_by_token("NOT_EXISTING_TOKEN")
104+
assert token_obj is None
113105

114-
# Delete token
115-
await sqlalchemy_access_token_db.delete(access_token)
116-
deleted_access_token = await sqlalchemy_access_token_db.get_by_token(
117-
access_token.token
118-
)
119-
assert deleted_access_token is None
106+
await dynamodb_access_token_db.delete(access_token)
107+
deleted_token = await dynamodb_access_token_db.get_by_token(access_token.token)
108+
assert deleted_token is None
120109

121110

122111
@pytest.mark.asyncio
123112
async def test_insert_existing_token(
124-
sqlalchemy_access_token_db: SQLAlchemyAccessTokenDatabase[AccessToken],
113+
dynamodb_access_token_db: DynamoDBAccessTokenDatabase[AccessToken],
125114
user_id: UUID4,
126115
):
127116
access_token_create = {"token": "TOKEN", "user_id": user_id}
128-
await sqlalchemy_access_token_db.create(access_token_create)
129117

130-
with pytest.raises(exc.IntegrityError):
131-
await sqlalchemy_access_token_db.create(access_token_create)
118+
await dynamodb_access_token_db.create(access_token_create)
119+
120+
with pytest.raises(Exception):
121+
await dynamodb_access_token_db.create(access_token_create)

0 commit comments

Comments
 (0)