How can I override my JWT auth dependency in the endponits in FastAPI testing?
SebaRossi94 opened this issue · comments
I managed to override my DB dependency for my testing in FastAPI but when I try to apply the same technique for overriding my JWT auth dependency I still get a 422 response with the following detail:
{'detail': [{'type': 'missing', 'loc': ['query', 'fake_jwt'], 'msg': 'Field required', 'input': None, 'url': 'https://errors.pydantic.dev/2.6/v/missing'}]}
I followed all documentation and suggested posts on this topic of overriding dependencies for testing and still haven't found my issue. Does anyone know what's the problem here?
Here are the involved codes:
conftest.py
def init_test_db(_app):
engine = create_engine(
settings.sql_alchemy_database_url,
connect_args={"check_same_thread": False},
)
def override_get_session():
with Session(engine, autoflush=True) as session:
with session.begin():
yield session
def override_get_session_no_transaction():
with Session(engine) as session:
yield session
_app.dependency_overrides[get_session] = override_get_session
_app.dependency_overrides[get_session_no_transaction] = (
override_get_session_no_transaction
)
SQLBaseModel.metadata.create_all(bind=engine)
with Session(engine) as session:
for user in fake_users.values():
session.add(user)
session.commit()
return engine
@pytest.fixture
def app_with_db():
from app.main import app
test_engine = init_test_db(app)
yield app
app.dependency_overrides = {}
drop_test_db(test_engine)
@pytest.fixture()
def app_with_db_and_jwt(app_with_db):
def override_jwt_dependency(fake_jwt):
print(fake_jwt)
return TokenData(id=1, email="jointhedarkside@empire.com")
app_with_db.dependency_overrides[validate_access_token] = override_jwt_dependency
yield app_with_db
test.py
def test_me_success(app_with_db_and_jwt):
darth_user = fake_users["darth"]
client = TestClient(app_with_db_and_jwt)
headers = {"Authorization": "Bearer fakejwt.super.fake"}
me_response = client.get("/users/me", headers=headers)
print(me_response.json())
assert me_response.status_code == 200
schemas.py
from pydantic import BaseModel
class TokenSchema(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
id: int
email: str
router.py
@users_router.get("/me", response_model=ResponseUserSchema)
def me(user_data: jwt_dependency, db: get_session_dependency):
user = db.exec(
select(User).where(User.email == user_data.email, User.id == user_data.id)
).first()
return user
dependencies.py
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/token")
token_dependency = Annotated[str, Depends(oauth2_scheme)]
def validate_access_token(token: token_dependency):
try:
token_payload = jwt.decode(
token, key=settings.jwt_secret_key, algorithms=settings.jwt_algorithm
)
email = token_payload.get("sub")
user_id = token_payload.get("id")
if email is None or user_id is None:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate user",
)
else:
return TokenData(id=user_id, email=email)
except JWTError as e:
logger.logger.exception(e)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate user"
)
jwt_dependency = Annotated[TokenData, Depends(validate_access_token)]