Skip to content

Commit

Permalink
Inject now_utc() into app builder to reduce monkeypatching in tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ceholden committed Dec 16, 2024
1 parent 94bf593 commit 84b9eec
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 39 deletions.
1 change: 0 additions & 1 deletion lambdas/link_fetcher/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ mangum = "*"

[dev-packages]
boto3-stubs = {version = "==1.17.10.0", extras = ["sqs", "ssm"]}
freezegun = "==1.0.0"
assertpy = "==1.1"
pytest = "==7.4.3"
responses = "==0.23.1"
Expand Down
23 changes: 7 additions & 16 deletions lambdas/link_fetcher/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions lambdas/link_fetcher/app/subscription_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ def process_notification(
logger.info(f"Rejected {search_result=} (unacceptable tile)")


def build_app(config: EndpointConfig) -> FastAPI:
def build_app(
config: EndpointConfig,
now_utc: Callable[[], datetime] = lambda: datetime.now(tz=timezone.utc),
) -> FastAPI:
"""Create FastAPI app"""
app = FastAPI()
app.add_middleware(
Expand Down Expand Up @@ -192,11 +195,11 @@ def post_notification(
logging.error("Unauthorized")
raise HTTPException(status_code=401, detail="Unauthorized")

# process notification
process_notification(
notification=notification,
accepted_tile_ids=accepted_tile_ids,
session_maker=session_maker,
now_utc=now_utc,
)
return Response(status_code=204)

Expand Down
3 changes: 2 additions & 1 deletion lambdas/link_fetcher/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ def sqs_client():

@pytest.fixture
def mock_sqs_queue(request, sqs_resource, monkeysession, sqs_client):
queue = sqs_resource.create_queue(QueueName=f"mock-queue-{request.node.name}"[:80])
request_name = hash(request.node.name)
queue = sqs_resource.create_queue(QueueName=f"mock-queue-{request_name}"[:80])
monkeysession.setenv("TO_DOWNLOAD_SQS_QUEUE_URL", queue.url)
return queue

Expand Down
48 changes: 29 additions & 19 deletions lambdas/link_fetcher/tests/test_subscription_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import json
from collections.abc import Iterator
from datetime import datetime
from datetime import datetime, timezone
from pathlib import Path
from typing import Callable
from unittest.mock import Mock, patch

import boto3
import httpx
import pytest
from db.models.granule import Granule
from fastapi import FastAPI
from freezegun import freeze_time
from moto import mock_aws
from sqlalchemy.orm import Session
from starlette.testclient import TestClient
Expand Down Expand Up @@ -195,16 +195,23 @@ def config(self) -> EndpointConfig:
)

@pytest.fixture
def app(
self, config: EndpointConfig, db_connection_secret, mock_sqs_queue
def now_utc(self, request) -> Callable[[], datetime]:
if callable(getattr(request, "param", None)):
return request.param
return lambda: datetime.now(tz=timezone.utc)

@pytest.fixture
def test_client(
self,
config: EndpointConfig,
db_connection_secret,
mock_sqs_queue,
now_utc,
) -> FastAPI:
self.endpoint_config = config
self.db_connection_secret = db_connection_secret
self.mock_sqs_queue = mock_sqs_queue
return build_app(config)

@pytest.fixture
def test_client(self, app: FastAPI) -> TestClient:
app = build_app(config, now_utc)
return TestClient(app)

def test_handles_new_created_event(
Expand All @@ -227,28 +234,31 @@ def test_handles_new_created_event(
assert resp.status_code == 204
mock_process_notification.assert_called_once()

@pytest.mark.parametrize(
"now_utc",
[lambda: datetime.fromisoformat("2024-09-12T14:52:06.118Z")],
indirect=True,
)
def test_handles_new_created_event_is_added(
self,
test_client: TestClient,
db_session: Session,
event_s2_created: dict,
now_utc,
):
"""Test happy path for handling subscription event, mocking DB and SQS
This is also distinguished by using a "recent" event notification that works
by freezing/rewinding time to acquisition date for the test duration.
"""
# we can't inject an older "utc_now" into `process_notification` so we have to
# patch `datetime.now()` with freezegun
with freeze_time(event_s2_created["value"]["PublicationDate"]):
resp = test_client.post(
"/events",
json=event_s2_created,
auth=(
self.endpoint_config.notification_username,
self.endpoint_config.notification_password,
),
)
resp = test_client.post(
"/events",
json=event_s2_created,
auth=(
self.endpoint_config.notification_username,
self.endpoint_config.notification_password,
),
)

# processed successfully but no content
resp.raise_for_status()
Expand Down

0 comments on commit 84b9eec

Please sign in to comment.