From 04c62d5d40c4b767707ba26539da24b7a18f678b Mon Sep 17 00:00:00 2001 From: Pieter Ouwerkerk Date: Mon, 10 Aug 2026 16:39:12 -0700 Subject: [PATCH] Fix order-dependent test failures from shared JWKS cache The module-global __jwkcache in clerk_backend_api.security.verifytoken is keyed only by JWT kid, so once any test verifies a session token with a valid secret key, the cached PEM lets every later test skip the JWKS fetch entirely. This made the credentialed error-path tests order-dependent: TestJwtVerificationAsync::test_verify_token_invalid_secret_key expects JWK_FAILED_TO_LOAD from a network round-trip that never happens after the sync TestJwtVerification::test_verify_token_remote_ok has warmed the cache. Deterministic repro (requires CLERK_SECRET_KEY and CLERK_SESSION_TOKEN): pytest "tests/test_verify_token.py::TestJwtVerification::test_verify_token_remote_ok" \ "tests/test_verify_token.py::TestJwtVerificationAsync::test_verify_token_invalid_secret_key" Add an autouse fixture that clears the cache before each test so every test starts cold. No production code is touched; the uncredentialed run is unchanged (59 passed, 14 skipped before and after). --- tests/conftest.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index e99b9140..ca494496 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,6 +2,7 @@ import pytest from typing import Optional, Union, List from clerk_backend_api import Clerk +from clerk_backend_api.security import verifytoken from clerk_backend_api.security.types import AuthenticateRequestOptions, VerifyTokenOptions @@ -9,6 +10,14 @@ def has_env_vars(env_vars: List[str]) -> bool: return all(os.getenv(var, "").strip() for var in env_vars) +@pytest.fixture(autouse=True) +def clear_jwk_cache(): + """The module-global JWKS cache in verifytoken is keyed only by kid, so a + key cached by one test lets later tests skip the network fetch entirely, + making error-path tests order-dependent. Start every test with a cold cache.""" + getattr(verifytoken, '__jwkcache').cache.clear() + + @pytest.fixture def secret_key() -> Optional[str]: """Secret Key from Clerk Dashboard."""