Skip to content

Commit 0ae4e78

Browse files
committed
Add missing tests
Signed-off-by: Federico Busetti <[email protected]>
1 parent 0e0891c commit 0ae4e78

File tree

3 files changed

+129
-3
lines changed

3 files changed

+129
-3
lines changed

tests/http_app/routes/test_auth.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
from unittest.mock import MagicMock, patch
2+
3+
import pytest
4+
from fastapi.security import HTTPAuthorizationCredentials, SecurityScopes
5+
from jwt import PyJWK, PyJWKClient
6+
from jwt.exceptions import DecodeError, PyJWKClientError
7+
8+
from common import AppConfig
9+
from common.config import AuthConfig
10+
from http_app.routes.auth import (
11+
MissingAuthorizationServerException,
12+
UnauthenticatedException,
13+
UnauthorizedException,
14+
_jwks_client,
15+
decode_jwt,
16+
)
17+
18+
19+
def test_jwks_client_raises_without_jwks_url():
20+
with pytest.raises(MissingAuthorizationServerException):
21+
_jwks_client(config=AppConfig(AUTH=AuthConfig(JWKS_URL=None)))
22+
23+
24+
def test_jwks_client_returns_a_client_with_jwks_url():
25+
result = _jwks_client(config=AppConfig(AUTH=AuthConfig(JWKS_URL="http://test.com")))
26+
assert isinstance(result, PyJWKClient)
27+
28+
29+
async def test_decode_jwt_raises_without_token():
30+
with pytest.raises(UnauthenticatedException):
31+
await decode_jwt(
32+
security_scopes=SecurityScopes(),
33+
config=AppConfig(),
34+
jwks_client=MagicMock(),
35+
token=None,
36+
)
37+
38+
39+
@pytest.mark.parametrize("exception", (PyJWKClientError, DecodeError))
40+
async def test_decode_jwt_raises_if_jwks_client_fails(exception):
41+
mock_jwks_client = MagicMock(spec=PyJWKClient)
42+
mock_jwks_client.get_signing_key_from_jwt = MagicMock(side_effect=exception)
43+
with pytest.raises(UnauthorizedException):
44+
await decode_jwt(
45+
security_scopes=SecurityScopes(),
46+
config=AppConfig(),
47+
jwks_client=mock_jwks_client,
48+
token=HTTPAuthorizationCredentials(
49+
scheme="bearer", credentials="some_token"
50+
),
51+
)
52+
53+
54+
async def test_decode_jwt_raises_if_decode_fails():
55+
returned_key = MagicMock(spec=PyJWK)
56+
returned_key.key = "some_key"
57+
mock_jwks_client = MagicMock(spec=PyJWKClient)
58+
mock_jwks_client.get_signing_key_from_jwt = MagicMock(return_value=returned_key)
59+
60+
with pytest.raises(UnauthorizedException):
61+
await decode_jwt(
62+
security_scopes=SecurityScopes(),
63+
config=AppConfig(),
64+
jwks_client=mock_jwks_client,
65+
token=HTTPAuthorizationCredentials(
66+
# The token cannot be decrypted and will trigger the exception
67+
scheme="bearer",
68+
credentials="some_token",
69+
),
70+
)
71+
72+
73+
async def test_decode_jwt_returns_the_decoded_jwt_payload():
74+
returned_key = MagicMock(spec=PyJWK)
75+
returned_key.key = "some_key"
76+
mock_jwks_client = MagicMock(spec=PyJWKClient)
77+
mock_jwks_client.get_signing_key_from_jwt = MagicMock(return_value=returned_key)
78+
79+
with patch("jwt.decode", return_value={"decoded": "token"}):
80+
result = await decode_jwt(
81+
security_scopes=SecurityScopes(),
82+
config=AppConfig(),
83+
jwks_client=mock_jwks_client,
84+
token=HTTPAuthorizationCredentials(
85+
# The token cannot be decrypted and will trigger the exception
86+
scheme="bearer",
87+
credentials="some_token",
88+
),
89+
)
90+
91+
assert result == {"decoded": "token"}

tests/http_app/routes/test_hello.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
1-
from fastapi import status
1+
from fastapi import Depends, FastAPI, status
2+
from fastapi.security import HTTPBearer
23
from fastapi.testclient import TestClient
34

5+
from http_app.routes.auth import decode_jwt
46

5-
async def test_hello_no_authentication_server(testapp):
7+
8+
async def _fake_decode_jwt(
9+
security_scopes=None,
10+
config=None,
11+
jwks_client=None,
12+
token=Depends(HTTPBearer()),
13+
):
14+
return {"token": token.credentials}
15+
16+
17+
async def test_hello_renders_what_returned_by_decoder(
18+
testapp: FastAPI,
19+
):
20+
testapp.dependency_overrides[decode_jwt] = _fake_decode_jwt
21+
ac = TestClient(app=testapp, base_url="http://test")
22+
response = ac.get(
23+
"/hello/",
24+
headers={"Authorization": "Bearer some_token"},
25+
)
26+
assert response.status_code == status.HTTP_200_OK
27+
assert '"token": "some_token"' in response.text
28+
29+
30+
async def test_hello_returns_403_without_token(testapp: FastAPI):
31+
testapp.dependency_overrides[decode_jwt] = _fake_decode_jwt
632
ac = TestClient(app=testapp, base_url="http://test")
733
response = ac.get("/hello/")
8-
assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
34+
assert response.status_code == status.HTTP_403_FORBIDDEN

tests/http_app/test_dependencies.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from common import AppConfig
2+
from http_app import context
3+
from http_app.dependencies import app_config
4+
5+
6+
def test_app_config_return_context_variable():
7+
config = AppConfig(APP_NAME="SomeOtherAppName")
8+
context.app_config.set(config)
9+
assert app_config() is config

0 commit comments

Comments
 (0)