How to Mock a Cache Key Schema Version Bump in Python
Show how to test a cache key schema bump by mocking the class-level version attribute with unittest.mock.
Python code
37 linesfrom unittest import mock
class VersionCache:
SCHEMA_VERSION = 1
def __init__(self, key_prefix="cache"):
self.key_prefix = key_prefix
def build_key(self, resource_id):
return f"{self.key_prefix}:schema-v{self.SCHEMA_VERSION}:{resource_id}"
def bump_schema(self):
# Simulated schema bump — increments the cache key version
self.SCHEMA_VERSION += 1
def main():
cache = VersionCache()
# Before schema bump
print("Before bump:", cache.build_key("user-123"))
# Bump the schema version
with mock.patch.object(VersionCache, "SCHEMA_VERSION", 2):
cache.SCHEMA_VERSION = 2 # simulate the bump within this mock context
print("During mock:", cache.build_key("user-123"))
# After mock ends, schema is back to original unless actually bumped
print("After mock:", cache.build_key("user-123"))
# Real bump
cache.bump_schema()
print("After real bump:", cache.build_key("user-123"))
if __name__ == "__main__":
main()
Output
Before bump: cache:schema-v1:user-123
During mock: cache:schema-v2:user-123
After mock: cache:schema-v1:user-123
After real bump: cache:schema-v2:user-123
How it works
The VersionCache class holds a class-level SCHEMA_VERSION that is used when building cache keys. By patching VersionCache.SCHEMA_VERSION inside a mock.patch.object context, you temporarily change the key version without modifying the actual class state. After the context exits, the mock is removed and the original value returns. A real bump_schema() method increments the version permanently, simulating a cache invalidation event in production. This pattern lets you test that old and new key namespaces differ without performing an actual bump.
Common mistakes
- Patching the instance attribute instead of the class attribute, which won't affect `build_key` if it reads from the class.
- Forgetting to restore the mock context properly, leaving the version changed outside the test.
- Assuming a mock on a class attribute persists after the `with` block ends.
Variations
- Use `unittest.mock.patch.object(VersionCache, 'SCHEMA_VERSION', 2)` with a decorator on a test function.
- Replace the class attribute with a module-level constant and patch it using `patch('module.CONSTANT', 2)`.
Real-world use cases
- Testing that a new cache namespace is used after deploying a schema change without waiting for the real rollout.
- Verifying that cache keys are versioned correctly when multiple app versions run simultaneously.
- Writing regression tests that simulate a cache format upgrade before actually releasing the bump in production.
Sponsored
More from Caching & Redis
- Cache Asides in Python with a Read-Through Loader easy
- Cache Data in Redis with Python easy
- Cache Penetration Null Object Mock in Python medium
- Cache Stampede Prevention with SingleFlight in Python medium
- Cache Warming with Python: Preload Hot Keys easy
- Coalescing duplicate in-flight requests: one shared result for concurrent callers hard
Keep learning
Related tutorials and quizzes for this topic.