Repository: getmoto/moto
Pull request #8918 (2025-05-22 21:14:26)

[APIGateway] Add ApiKeyNotFoundException for update/delete_api_key
This PR:
- Raises `ApiKeyNotFoundException` for `update_api_key` when the key is not found
- Raises `ApiKeyNotFoundException` for `delete_api_key` when the key is not found
- Adds test cases for both functions

Previously these functions would raise `KeyError` instead of what AWS would raise in this case.

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/8918?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 92.85%. Comparing base [(`c04116b`)](https://app.codecov.io/gh/getmoto/moto/commit/c04116b3556f8c5d309934ec322ca3ae93aaa34f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`7c103fc`)](https://app.codecov.io/gh/getmoto/moto/commit/7c103fcab64921f8c6e4e08d41bc6e1c92d19b67?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #8918   +/-   ##
=======================================
  Coverage   92.85%   92.85%           
=======================================
  Files        1282     1282           
  Lines      112028   112032    +4     
=======================================
+ Hits       104027   104032    +5     
+ Misses       8001     8000    -1     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/8918/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/8918/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `27.95% <0.00%> (-0.01%)` | :arrow_down: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/8918/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `92.83% <100.00%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/8918?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>

Patch:
diff --git a/moto/apigateway/models.py b/moto/apigateway/models.py
index 438f126f2..2f8562b87 100644
--- a/moto/apigateway/models.py
+++ b/moto/apigateway/models.py
@@ -2198,10 +2198,14 @@ class APIGatewayBackend(BaseBackend):
         return self.keys[api_key_id]
 
     def update_api_key(self, api_key_id: str, patch_operations: Any) -> ApiKey:
+        if api_key_id not in self.keys:
+            raise ApiKeyNotFoundException()
         key = self.keys[api_key_id]
         return key.update_operations(patch_operations)
 
     def delete_api_key(self, api_key_id: str) -> None:
+        if api_key_id not in self.keys:
+            raise ApiKeyNotFoundException()
         self.keys.pop(api_key_id)
 
     def create_usage_plan(self, payload: Any) -> UsagePlan:


Test patch:
diff --git a/tests/test_apigateway/test_apigateway.py b/tests/test_apigateway/test_apigateway.py
index ba2ca674e..f678c8586 100644
--- a/tests/test_apigateway/test_apigateway.py
+++ b/tests/test_apigateway/test_apigateway.py
@@ -1953,6 +1953,27 @@ def test_get_api_key_unknown_apikey():
     assert err["Code"] == "NotFoundException"
 
 
+@mock_aws
+def test_update_api_key_unknown_apikey():
+    client = boto3.client("apigateway", region_name="us-east-1")
+    patch_operations = [{"op": "replace", "path": "/name", "value": "test"}]
+    with pytest.raises(ClientError) as ex:
+        client.update_api_key(apiKey="unknown", patchOperations=patch_operations)
+    err = ex.value.response["Error"]
+    assert err["Message"] == "Invalid API Key identifier specified"
+    assert err["Code"] == "NotFoundException"
+
+
+@mock_aws
+def test_delete_api_key_unknown_apikey():
+    client = boto3.client("apigateway", region_name="us-east-1")
+    with pytest.raises(ClientError) as ex:
+        client.delete_api_key(apiKey="unknown")
+    err = ex.value.response["Error"]
+    assert err["Message"] == "Invalid API Key identifier specified"
+    assert err["Code"] == "NotFoundException"
+
+
 @mock_aws
 def test_get_rest_api_without_id():
     client = boto3.client("apigateway", region_name="us-east-1")