def test_handler_metadata_completed_empty(lambda_module, context, ddb_record_metadata_completed, event_metadata_failed, order, order_products): """ Test handler() with a metadata completed item but no products """ event_metadata_failed = copy.deepcopy(event_metadata_failed) table = mock_table(lambda_module.table, "query", ["orderId", "productId"]) # Stubbing Event Bridge eventbridge = stub.Stubber(lambda_module.eventbridge) # Ignore time and detail event_metadata_failed["Time"] = stub.ANY event_metadata_failed["Detail"] = stub.ANY expected_params = {"Entries": [event_metadata_failed]} eventbridge.add_response("put_events", {}, expected_params) eventbridge.activate() event = {"Records": [ddb_record_metadata_completed]} lambda_module.handler(event, context) table.assert_no_pending_responses() table.deactivate() eventbridge.assert_no_pending_responses() eventbridge.deactivate()
def test_handler(monkeypatch, lambda_module, context): """ Test handler() """ service_name = "ecommerce.test" event = {"source": service_name, "message": "test_event"} connection_ids = [str(uuid.uuid4()) for _ in range(100)] called = {"get_connection_ids": False, "send_event": False} def get_connection_ids(service_name_got: str) -> List[str]: assert service_name == service_name called["get_connection_ids"] = True return connection_ids def send_event(event_got: dict, connection_ids_got: list): assert event == event_got assert connection_ids == connection_ids_got called["send_event"] = True monkeypatch.setattr(lambda_module, "get_connection_ids", get_connection_ids) monkeypatch.setattr(lambda_module, "send_event", send_event) lambda_module.handler(event, context) for k in called.keys(): assert called[k] == True
def test_handler_created(lambda_module, context, order, order_products, order_metadata): """ Test handler() with OrderCreated """ table = mock_table( lambda_module.table, "get_item", ["orderId", "productId"] ) mock_table( table, "batch_write_item", ["orderId", "productId"], table_name=lambda_module.table.name, items=[ {"PutRequest": {"Item": product}} for product in order_products ] ) order_metadata = copy.deepcopy(order_metadata) order_metadata["newDate"] = order_metadata["modifiedDate"] mock_table( table, "put_item", ["orderId", "productId"], table_name=lambda_module.table.name, items=order_metadata ) lambda_module.handler({ "source": "ecommerce.orders", "resources": [order["orderId"]], "detail-type": "OrderCreated", "detail": order }, context) table.assert_no_pending_responses() table.deactivate()
def test_handler(lambda_module, event, context, order, url, ddb_item): """ Test handler() """ # Mock boto3 table = mock_table( lambda_module.table, "get_item", ["orderId"] ) table = mock_table( table, "put_item", ["orderId"], items=ddb_item, table_name=lambda_module.table.name ) with requests_mock.Mocker() as m: # Mock requests m.get(url, text=json.dumps(order)) lambda_module.handler(event, context) # Assertions assert m.called assert m.call_count == 1 assert m.request_history[0].method == "GET" assert m.request_history[0].url == url table.assert_no_pending_responses() table.deactivate()
def test_handler(monkeypatch, lambda_module, context, order): """ Test handler() """ test_cases = [{ "status": "FULFILLED", "source": "ecommerce.delivery", "detail-type": "DeliveryCompleted", "called": True }, { "status": "DELIVERY_FAILED", "source": "ecommerce.delivery", "detail-type": "DeliveryFailed", "called": True }, { "status": "PACKAGED", "source": "ecommerce.warehouse", "detail-type": "PackageCreated", "called": True, "products": True }, { "status": "PACKAGING_FAILED", "source": "ecommerce.warehouse", "detail-type": "PackagingFailed", "called": True }, { "status": "UNKNOWN", "source": "ecommerce.warehouse", "detail-type": "UnknownDetailType", "called": False }, { "status": "UNKNOWN", "source": "ecommerce.delivery", "detail-type": "UnknownDetailType", "called": False }, { "status": "UNKNOWN", "source": "UNKNOWN", "detail-type": "UnknownDetailType", "called": False }] for test_case in test_cases: def update_order(order_id: str, status: str, products=None) -> None: assert test_case["called"] assert order_id == "ORDER_ID" assert status == test_case["status"] if test_case.get("products", False): assert products is not None monkeypatch.setattr(lambda_module, "update_order", update_order) event = { "resources": ["ORDER_ID"], "source": test_case["source"], "detail-type": test_case["detail-type"], "detail": order } lambda_module.handler(event, context)
def test_handler_wrong_event_detail(lambda_module, event, context): """ Test handler() with an incorrect event """ event = copy.deepcopy(event) event["detail"] = {} with pytest.raises(KeyError) as excinfo: lambda_module.handler(event, context)
def test_handler_wrong_event_detail_type(lambda_module, event, context): """ Test handler() with an incorrect event """ event = copy.deepcopy(event) event["detail-type"] = "WRONG" with pytest.raises(AssertionError) as excinfo: lambda_module.handler(event, context)
def test_handler_wrong_order(lambda_module, event, context, order, url): """ Test handler() with a non-existing order """ with requests_mock.Mocker() as m: m.get(url, status_code=404, text=json.dumps({"message": "Order not found"})) with pytest.raises(Exception, match="Failed to retrieve order .*") as excinfo: lambda_module.handler(event, context) assert m.called assert m.call_count == 1 assert m.request_history[0].method == "GET" assert m.request_history[0].url == url
def test_handler_missing_total(monkeypatch, lambda_module, context, apigateway_event, payment_token, total): """ Test handler() with a missing total """ def validate_payment_token(payment_token: str, total: int) -> bool: # This should never be called assert False return True monkeypatch.setattr(lambda_module, "validate_payment_token", validate_payment_token) event = apigateway_event( iam="USER_ARN", body=json.dumps({ "paymentToken": payment_token, }) ) response = lambda_module.handler(event, context) assert response["statusCode"] == 400 assert "body" in response body = json.loads(response["body"]) assert "ok" not in body assert "message" in body assert isinstance(body["message"], str) assert "total" in body["message"]
def test_handler(lambda_module, apigateway_event, order, context): """ Test handler() """ # Stub boto3 table = stub.Stubber(lambda_module.table.meta.client) response = { "Item": {k: TypeSerializer().serialize(v) for k, v in order.items()}, # We do not use ConsumedCapacity "ConsumedCapacity": {} } expected_params = { "TableName": lambda_module.TABLE_NAME, "Key": { "orderId": order["orderId"] } } table.add_response("get_item", response, expected_params) table.activate() # Send request response = lambda_module.handler(apigateway_event, context) # Remove stub table.assert_no_pending_responses() table.deactivate() assert response["statusCode"] == 200 assert "body" in response body = json.loads(response["body"]) compare_dict(order, body)
def test_handler(monkeypatch, lambda_module, context, apigateway_event, order): """ Test handler() """ event = apigateway_event(iam="USER_ARN", body=json.dumps({ "products": order["products"], "address": order["address"] })) def get_pricing(products: List[dict], address: dict) -> int: assert products == order["products"] assert address == order["address"] return 1000 monkeypatch.setattr(lambda_module, "get_pricing", get_pricing) retval = lambda_module.handler(event, context) assert "statusCode" in retval assert retval["statusCode"] == 200 assert "body" in retval body = json.loads(retval["body"]) assert "pricing" in body assert body["pricing"] == 1000
def test_handler_no_id(monkeypatch, lambda_module, context, apigateway_event): """ Test handler() """ connection_id = str(uuid.uuid4()) event = apigateway_event() calls = {"store_id": 0, "enable_rule": 0} def store_id(connection_id_req: str): calls["store_id"] += 1 assert connection_id_req == connection_id monkeypatch.setattr(lambda_module, "store_id", store_id) def enable_rule(): calls["enable_rule"] += 1 monkeypatch.setattr(lambda_module, "enable_rule", enable_rule) result = lambda_module.handler(event, context) assert result["statusCode"] == 400 assert calls["store_id"] == 0 assert calls["enable_rule"] == 0
def test_handler(monkeypatch, lambda_module, context, apigateway_event, payment_token, total): """ Test handler() """ def validate_payment_token(pt: str, a: int) -> bool: assert pt == payment_token assert a == total return True monkeypatch.setattr(lambda_module, "validate_payment_token", validate_payment_token) event = apigateway_event( iam="USER_ARN", body=json.dumps({ "paymentToken": payment_token, "total": total }) ) response = lambda_module.handler(event, context) assert response["statusCode"] == 200 assert "body" in response body = json.loads(response["body"]) assert "ok" in body assert body["ok"] == True
def test_handler(monkeypatch, lambda_module, context, apigateway_event): """ Test handler() """ connection_id = str(uuid.uuid4()) event = apigateway_event() event["requestContext"] = {"connectionId": connection_id} calls = { "delete_id": 0, "disable_rule": 0 } def delete_id(connection_id_req: str): calls["delete_id"] += 1 assert connection_id_req == connection_id monkeypatch.setattr(lambda_module, "delete_id", delete_id) def disable_rule(): calls["disable_rule"] += 1 monkeypatch.setattr(lambda_module, "disable_rule", disable_rule) result = lambda_module.handler(event, context) assert result["statusCode"] == 200 assert calls["delete_id"] == 1 assert calls["disable_rule"] == 1
def test_handler_not_found(lambda_module, apigateway_event, order, context): """ Test handler() with an unknown order ID """ # Stub boto3 table = stub.Stubber(lambda_module.table.meta.client) response = { # We do not use ConsumedCapacity "ConsumedCapacity": {} } expected_params = { "TableName": lambda_module.TABLE_NAME, "Key": { "orderId": order["orderId"] } } table.add_response("get_item", response, expected_params) table.activate() # Send request response = lambda_module.handler(apigateway_event, context) # Remove stub table.assert_no_pending_responses() table.deactivate() assert response["statusCode"] == 404 assert "body" in response body = json.loads(response["body"]) assert "message" in body assert isinstance(body["message"], str)
def test_handler_validation_failure(monkeypatch, lambda_module, context, order): """ Test handler() with failing validation """ def validate_true(order: dict) -> Tuple[bool, str]: return (False, "Something went wrong") def store_order(order: dict) -> None: pass monkeypatch.setattr(lambda_module, "validate_delivery", validate_true) monkeypatch.setattr(lambda_module, "validate_payment", validate_true) monkeypatch.setattr(lambda_module, "validate_products", validate_true) monkeypatch.setattr(lambda_module, "store_order", store_order) user_id = order["userId"] order = copy.deepcopy(order) del order["userId"] response = lambda_module.handler({ "order": order, "userId": user_id }, context) print(response) assert response["success"] == False assert len(response.get("errors", [])) > 0
def test_handler_wrong_order(monkeypatch, lambda_module, context, order): """ Test handler() with an incorrect order """ async def validate_true(order: dict) -> Tuple[bool, str]: return (True, "") def store_order(order: dict) -> None: pass monkeypatch.setattr(lambda_module, "validate_delivery", validate_true) monkeypatch.setattr(lambda_module, "validate_payment", validate_true) monkeypatch.setattr(lambda_module, "validate_products", validate_true) monkeypatch.setattr(lambda_module, "store_order", store_order) user_id = order["userId"] order = copy.deepcopy(order) del order["userId"] del order["paymentToken"] response = lambda_module.handler({ "order": order, "userId": user_id }, context) print(response) assert response["success"] == False assert len(response.get("errors", [])) > 0
def test_handler(monkeypatch, lambda_module, context, order): """ Test handler() """ def validate_true(order: dict) -> Tuple[bool, str]: return (True, "") def store_order(order: dict) -> None: pass monkeypatch.setattr(lambda_module, "validate_delivery", validate_true) monkeypatch.setattr(lambda_module, "validate_payment", validate_true) monkeypatch.setattr(lambda_module, "validate_products", validate_true) monkeypatch.setattr(lambda_module, "store_order", store_order) user_id = order["userId"] order = copy.deepcopy(order) del order["userId"] response = lambda_module.handler({ "order": order, "userId": user_id }, context) print(response) assert response["success"] == True assert len(response.get("errors", [])) == 0 assert "order" in response compare_dict(order, response["order"])
def test_handler_invalid_body(monkeypatch, lambda_module, context, apigateway_event): """ Test handler() without a correct JSON body """ connection_id = str(uuid.uuid4()) service_name = "ecommerce.test" event = apigateway_event() event["requestContext"] = {"connectionId": connection_id} event["body"] = "{" calls = { "register_service": 0 } def register_service(connection_id_req: str, service_name_req: str): calls["register_service"] += 1 assert connection_id_req == connection_id assert service_name_req == service_name monkeypatch.setattr(lambda_module, "register_service", register_service) result = lambda_module.handler(event, context) assert result["statusCode"] == 400 assert calls["register_service"] == 0
def test_handler_no_id(monkeypatch, lambda_module, context, apigateway_event): """ Test handler() without connectionId """ connection_id = str(uuid.uuid4()) service_name = "ecommerce.test" event = apigateway_event() event["body"] = json.dumps({"serviceName": service_name}) calls = { "register_service": 0 } def register_service(connection_id_req: str, service_name_req: str): calls["register_service"] += 1 assert connection_id_req == connection_id assert service_name_req == service_name monkeypatch.setattr(lambda_module, "register_service", register_service) result = lambda_module.handler(event, context) assert result["statusCode"] == 400 assert calls["register_service"] == 0
def test_handler_correct(monkeypatch, lambda_module, apigateway_event, context, product): """ Test the function handler against an incorrect product """ def validate_products(products): return [], "" monkeypatch.setattr(lambda_module, "validate_products", validate_products) # Create request event = apigateway_event( iam="USER_ARN", body=json.dumps({"products": [product]}) ) # Parse request response = lambda_module.handler(event, context) # Check response assert response["statusCode"] == 200 # There should be 1 item in the response body response_body = json.loads(response["body"]) assert "message" in response_body assert isinstance(response_body["message"], str) assert "products" not in response_body
def test_handler_missing_products(monkeypatch, lambda_module, apigateway_event, context, product): """ Test the function handler with missing 'products' in request body """ def validate_products(products): assert False # This should never be called monkeypatch.setattr(lambda_module, "validate_products", validate_products) # Create request event = apigateway_event( iam="USER_ARN", body=json.dumps({}) ) # Parse request response = lambda_module.handler(event, context) # Check response assert response["statusCode"] == 400 # There should be a reason in the response body response_body = json.loads(response["body"]) assert "message" in response_body assert isinstance(response_body["message"], str)
def test_handler_wrong_event(lambda_module, context, postconfirm_data): """ Test handler() """ postconfirm_data["input"]["triggerSource"] += "_WRONG_EVENT" # Prepare stub eventbridge = stub.Stubber(lambda_module.eventbridge) eventbridge.activate() # Execute function lambda_module.handler(postconfirm_data["input"], context) # End eventbridge.assert_no_pending_responses() eventbridge.deactivate()
def test_handler_nothing(lambda_module, context, order, ddb_record_new): """ Test handler() with records that should not create events """ # Prepare event event = {"Records": [ddb_record_new]} # Stub eventbridge = stub.Stubber(lambda_module.eventbridge) eventbridge.activate() # Send request lambda_module.handler(event, context) # Check that events were sent eventbridge.assert_no_pending_responses() eventbridge.deactivate()
def test_handler(monkeypatch, lambda_module, context, order_id, payment_token): """ Test handler() """ event = { "source": "ecommerce.delivery", "detail-type": "DeliveryFailed", "resources": [order_id], "detail": { "old": { "orderId": order_id, "total": 300 }, "new": { "orderId": order_id, "total": 200 } } } called = [] def update_payment_amount(p: str, a: int) -> None: called.append("update_payment_amount") assert a == 200 assert p == payment_token def get_payment_token(o: str) -> str: called.append("get_payment_token") assert o == order_id return payment_token monkeypatch.setattr(lambda_module, "get_payment_token", get_payment_token) monkeypatch.setattr(lambda_module, "update_payment_amount", update_payment_amount) lambda_module.handler(event, context) assert "update_payment_amount" in called assert "get_payment_token" in called
def test_handler(lambda_module, context, postconfirm_data): """ Test handler() """ output = copy.deepcopy(postconfirm_data["output"]) output["Time"] = stub.ANY # Prepare stub eventbridge = stub.Stubber(lambda_module.eventbridge) response = {} expected_params = {"Entries": [output]} eventbridge.add_response("put_events", response, expected_params) eventbridge.activate() # Execute function lambda_module.handler(postconfirm_data["input"], context) # End eventbridge.assert_no_pending_responses() eventbridge.deactivate()
def test_handler(monkeypatch, lambda_module, context, order_id, payment_token): """ Test handler() """ event = { "source": "ecommerce.delivery", "detail-type": "DeliveryFailed", "resources": [order_id], "detail": { "orderId": order_id, "total": 1234 } } called = [] def cancel_payment(p: str) -> None: called.append("cancel_payment") assert p == payment_token def get_payment_token(o: str) -> str: called.append("get_payment_token") assert o == order_id return payment_token def delete_payment_token(o: str) -> str: called.append("delete_payment_token") assert o == order_id monkeypatch.setattr(lambda_module, "get_payment_token", get_payment_token) monkeypatch.setattr(lambda_module, "delete_payment_token", delete_payment_token) monkeypatch.setattr(lambda_module, "cancel_payment", cancel_payment) lambda_module.handler(event, context) assert "cancel_payment" in called assert "get_payment_token" in called assert "delete_payment_token" in called
def test_handler(lambda_module, context, insert_data): """ Test the Lambda function handler """ # Prepare Lambda event and context event = {"Records": [insert_data["record"]]} # Stubbing boto3 eventbridge = stub.Stubber(lambda_module.eventbridge) # Ignore time insert_data["event"]["Time"] = stub.ANY expected_params = {"Entries": [insert_data["event"]]} eventbridge.add_response("put_events", {}, expected_params) eventbridge.activate() # Send request lambda_module.handler(event, context) # Check that events were sent eventbridge.assert_no_pending_responses() eventbridge.deactivate()
def test_handler(monkeypatch, lambda_module, context, order_id, payment_token): """ Test handler() """ event = { "source": "ecommerce.orders", "detail-type": "OrderCreated", "resources": [order_id], "detail": { "orderId": order_id, "paymentToken": payment_token } } def save_payment_token(o: str, p: str): assert o == order_id assert p == payment_token monkeypatch.setattr(lambda_module, "save_payment_token", save_payment_token) lambda_module.handler(event, context)
def test_handler_deleted(lambda_module, context, order, order_products, order_metadata): """ Test handler() with OrderDeleted """ table = mock_table( lambda_module.table, "get_item", ["orderId", "productId"], items=order_metadata ) mock_table( table, "batch_write_item", ["orderId", "productId"], table_name=lambda_module.table.name, items=[ {"DeleteRequest": {"Key": { "orderId": product["orderId"], "productId": product["productId"] }}} for product in order_products ] ) mock_table( table, "delete_item", ["orderId", "productId"], table_name=lambda_module.table.name, items=order_metadata ) lambda_module.handler({ "source": "ecommerce.orders", "resources": [order["orderId"]], "detail-type": "OrderDeleted", "detail": order }, context) table.assert_no_pending_responses() table.deactivate()