From 9ce92411a98ebbc02a04ce47033e145060905bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leynier=20Guti=C3=A9rrez=20Gonz=C3=A1lez?= Date: Sat, 25 Jan 2025 18:01:43 -0600 Subject: [PATCH] tests: add some tests --- fastapi_cache_plus/__init__.py | 1 + fastapi_cache_plus/backends/base.py | 16 +++++------ tests/memory_tests.py | 43 ++++++++++++++++------------- tests/redis_tests.py | 24 ++++++---------- tests/registry_tests.py | 20 ++++++++------ tests/ttldict_tests.py | 42 ++++++++++++++++------------ 6 files changed, 79 insertions(+), 67 deletions(-) diff --git a/fastapi_cache_plus/__init__.py b/fastapi_cache_plus/__init__.py index 63650cf..8a7700a 100644 --- a/fastapi_cache_plus/__init__.py +++ b/fastapi_cache_plus/__init__.py @@ -6,3 +6,4 @@ async def close_caches() -> None: for cache in caches.all(): await cache.close() + caches.flush() diff --git a/fastapi_cache_plus/backends/base.py b/fastapi_cache_plus/backends/base.py index 184deee..8ae23d4 100644 --- a/fastapi_cache_plus/backends/base.py +++ b/fastapi_cache_plus/backends/base.py @@ -6,25 +6,25 @@ class BaseCacheBackend(Generic[KT, VT]): async def add(self, key: KT, value: VT, **kwargs) -> bool: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def get(self, key: KT, default: VT = None, **kwargs) -> VT: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def set(self, key: KT, value: VT, **kwargs) -> bool: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def expire(self, key: KT, ttl: int) -> bool: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def exists(self, *keys: KT) -> bool: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def delete(self, key: KT) -> bool: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def flush(self) -> None: - raise NotImplementedError + raise NotImplementedError # pragma: no cover async def close(self) -> None: - raise NotImplementedError + raise NotImplementedError # pragma: no cover diff --git a/tests/memory_tests.py b/tests/memory_tests.py index f345431..d492675 100644 --- a/tests/memory_tests.py +++ b/tests/memory_tests.py @@ -16,7 +16,6 @@ def f_backend() -> InMemoryCacheBackend: @pytest.mark.asyncio async def test_should_add_n_get_data(f_backend: InMemoryCacheBackend) -> None: is_added = await f_backend.add(TEST_KEY, TEST_VALUE) - assert is_added is True assert await f_backend.get(TEST_KEY) == TEST_VALUE @@ -27,7 +26,6 @@ async def test_add_should_return_false_if_key_exists( ) -> None: await f_backend.add(TEST_KEY, TEST_VALUE) is_added = await f_backend.add(TEST_KEY, TEST_VALUE) - assert is_added is False @@ -37,19 +35,15 @@ async def test_should_return_default_if_key_not_exists( ) -> None: default = "3.14159" fetched_value = await f_backend.get("not_exists", default) - assert fetched_value == default @pytest.mark.asyncio async def test_set_should_rewrite_value(f_backend: InMemoryCacheBackend) -> None: eulers_number = "2.71828" - await f_backend.add(TEST_KEY, TEST_VALUE) await f_backend.set(TEST_KEY, eulers_number) - fetched_value = await f_backend.get(TEST_KEY) - assert fetched_value == eulers_number @@ -57,9 +51,7 @@ async def test_set_should_rewrite_value(f_backend: InMemoryCacheBackend) -> None async def test_delete_should_remove_from_cache(f_backend: InMemoryCacheBackend) -> None: await f_backend.add(TEST_KEY, TEST_VALUE) await f_backend.delete(TEST_KEY) - fetched_value = await f_backend.get(TEST_KEY) - assert fetched_value is None @@ -69,9 +61,7 @@ async def test_flush_should_remove_all_objects_from_cache( ) -> None: await f_backend.add("pi", "3.14159") await f_backend.add("golden_ratio", "1.61803") - await f_backend.flush() - assert await f_backend.get("pi") is None assert await f_backend.get("golden_ratio") is None @@ -89,7 +79,6 @@ async def test_should_set_value_with_ttl( ) -> None: await f_backend.set(key, value, ttl=ttl) fetched_value = await f_backend.get(key) - assert fetched_value == expected @@ -102,11 +91,14 @@ async def test_should_set_value_with_ttl( ], ) async def test_should_add_value_with_ttl( - key: Hashable, value: Any, ttl: int, expected: Any, f_backend: InMemoryCacheBackend + key: Hashable, + value: Any, + ttl: int, + expected: Any, + f_backend: InMemoryCacheBackend, ) -> None: await f_backend.add(key, value, ttl=ttl) fetched_value = await f_backend.get(key) - assert fetched_value == expected @@ -118,11 +110,11 @@ async def test_should_add_value_with_ttl( ], ) async def test_key_should_check_for_exists( - keys: Tuple[Hashable], f_backend: InMemoryCacheBackend + keys: Tuple[Hashable], + f_backend: InMemoryCacheBackend, ) -> None: for key in keys: await f_backend.set(key, key) - assert await f_backend.exists(*keys) is True @@ -135,11 +127,13 @@ async def test_key_should_check_for_exists( ], ) async def test_key_should_check_for_exists_with_ttl( - keys: Tuple[Hashable], ttl: int, exists: bool, f_backend: InMemoryCacheBackend + keys: Tuple[Hashable], + ttl: int, + exists: bool, + f_backend: InMemoryCacheBackend, ) -> None: for key in keys: await f_backend.set(key, key, ttl=ttl) - assert await f_backend.exists(*keys) is exists @@ -165,10 +159,21 @@ async def test_should_return_false_if_keys_not_exist( ], ) async def test_expire_from_cache( - key: Hashable, value: Any, ttl: int, expected: Any, f_backend: InMemoryCacheBackend + key: Hashable, + value: Any, + ttl: int, + expected: Any, + f_backend: InMemoryCacheBackend, ) -> None: await f_backend.add(key, value) await f_backend.expire(key, ttl) fetched_value = await f_backend.get(key) - assert fetched_value == expected + + +@pytest.mark.asyncio +async def test_close_should_not_raise_exception( + f_backend: InMemoryCacheBackend, +) -> None: + await f_backend.close() + assert True diff --git a/tests/redis_tests.py b/tests/redis_tests.py index 32352e4..47a4e29 100644 --- a/tests/redis_tests.py +++ b/tests/redis_tests.py @@ -22,7 +22,6 @@ def f_backend() -> RedisCacheBackend: @pytest.mark.asyncio async def test_should_add_n_get_data(f_backend: RedisCacheBackend) -> None: is_added = await f_backend.add(TEST_KEY, TEST_VALUE) - assert is_added is True assert await f_backend.get(TEST_KEY) == TEST_VALUE @@ -32,7 +31,6 @@ async def test_should_add_n_get_data_no_encoding(f_backend: RedisCacheBackend) - NO_ENCODING_KEY = "bytes" NO_ENCODING_VALUE = b"test" is_added = await f_backend.add(NO_ENCODING_KEY, NO_ENCODING_VALUE) - assert is_added is True assert await f_backend.get(NO_ENCODING_KEY, encoding=None) == bytes( NO_ENCODING_VALUE @@ -45,7 +43,6 @@ async def test_add_should_return_false_if_key_exists( ) -> None: await f_backend.add(TEST_KEY, TEST_VALUE) is_added = await f_backend.add(TEST_KEY, TEST_VALUE) - assert is_added is False @@ -55,7 +52,6 @@ async def test_should_return_default_if_key_not_exists( ) -> None: default = "3.14159" fetched_value = await f_backend.get("not_exists", default) - assert fetched_value == default @@ -101,19 +97,15 @@ async def test_should_check_is_several_keys_exists( ) -> None: for key, value in preset: await f_backend.add(key, value) - assert await f_backend.exists(*keys) == exists @pytest.mark.asyncio async def test_set_should_rewrite_value(f_backend: RedisCacheBackend) -> None: eulers_number = "2.71828" - await f_backend.add(TEST_KEY, TEST_VALUE) await f_backend.set(TEST_KEY, eulers_number) - fetched_value = await f_backend.get(TEST_KEY) - assert fetched_value == eulers_number @@ -121,9 +113,7 @@ async def test_set_should_rewrite_value(f_backend: RedisCacheBackend) -> None: async def test_delete_should_remove_from_cache(f_backend: RedisCacheBackend) -> None: await f_backend.add(TEST_KEY, TEST_VALUE) await f_backend.delete(TEST_KEY) - fetched_value = await f_backend.get(TEST_KEY) - assert fetched_value is None @@ -136,12 +126,15 @@ async def test_delete_should_remove_from_cache(f_backend: RedisCacheBackend) -> ], ) async def test_expire_from_cache( - key: RedisKey, value: Any, ttl: int, expected: Any, f_backend: RedisCacheBackend + key: RedisKey, + value: Any, + ttl: int, + expected: Any, + f_backend: RedisCacheBackend, ) -> None: await f_backend.add(key, value) await f_backend.expire(key, ttl) fetched_value = await f_backend.get(key) - assert fetched_value == expected @@ -151,9 +144,7 @@ async def test_flush_should_remove_all_objects_from_cache( ) -> None: await f_backend.add("pi", "3.14159") await f_backend.add("golden_ratio", "1.61803") - await f_backend.flush() - assert await f_backend.get("pi") is None assert await f_backend.get("golden_ratio") is None @@ -179,7 +170,10 @@ async def test_close_should_close_connection(f_backend: RedisCacheBackend) -> No ], ) async def test_scalar_types( - key: RedisKey, value: Any, expected: Any, f_backend: RedisCacheBackend + key: RedisKey, + value: Any, + expected: Any, + f_backend: RedisCacheBackend, ) -> None: await f_backend.set(key, value) assert await f_backend.get(key) == expected diff --git a/tests/registry_tests.py b/tests/registry_tests.py index 0650206..a59edfc 100644 --- a/tests/registry_tests.py +++ b/tests/registry_tests.py @@ -2,6 +2,7 @@ import pytest +from fastapi_cache_plus import close_caches from fastapi_cache_plus.backends.memory import CACHE_KEY, BaseCacheBackend from fastapi_cache_plus.registry import CacheRegistry @@ -24,7 +25,6 @@ def test_get_from_registry_should_return_cache_instance( ) -> None: cache = BaseCacheBackend() cache_registry.set(CACHE_KEY, cache) - assert cache_registry.get(CACHE_KEY) == cache @@ -32,10 +32,8 @@ def test_retrieve_all_registered_caches_from_registry( cache_registry: CacheRegistry, ) -> None: cache = BaseCacheBackend() - cache_registry.set(CACHE_KEY, cache) cache_registry.set("OTHER_CACHE_KEY", cache) - assert cache_registry.all() == (cache, cache) @@ -44,7 +42,6 @@ def test_registry_should_raise_error_on_dublicate_cache_key( ) -> None: cache = BaseCacheBackend() cache_registry.set(CACHE_KEY, cache) - with pytest.raises(NameError, match="Cache with the same name already registered"): cache_registry.set(CACHE_KEY, cache) @@ -53,7 +50,6 @@ def test_remove_cache_from_registry(cache_registry: CacheRegistry) -> None: cache = BaseCacheBackend() cache_registry.set(CACHE_KEY, cache) cache_registry.remove(CACHE_KEY) - assert cache_registry.get(CACHE_KEY) is None @@ -68,16 +64,24 @@ def test_flush_should_remove_all_registered_cashes( cache_registry: CacheRegistry, ) -> None: cache = BaseCacheBackend() - cache_registry.set(CACHE_KEY, cache) cache_registry.set("OTHER_CACHE_KEY", cache) - cache_registry.flush() - assert cache_registry.get(CACHE_KEY) is None assert cache_registry.get("OTHER_CACHE_KEY") is None +@pytest.mark.asyncio +async def test_close_caches_should_not_raise_exception( + cache_registry: CacheRegistry, +) -> None: + cache = BaseCacheBackend() + cache_registry.set(CACHE_KEY, cache) + cache_registry.set("OTHER_CACHE_KEY", cache) + await close_caches() + assert cache_registry.get(CACHE_KEY) is None + + @pytest.mark.backwards def test_registry_can_be_imported_by_older_path() -> None: import importlib diff --git a/tests/ttldict_tests.py b/tests/ttldict_tests.py index 4cb99b5..029184b 100644 --- a/tests/ttldict_tests.py +++ b/tests/ttldict_tests.py @@ -12,9 +12,9 @@ def ttl_dict() -> TTLDict: global MOCKED_DICT MOCKED_DICT = dict() - with mock.patch( - "fastapi_cache_plus.backends.utils.ttldict.dict", return_value=MOCKED_DICT + "fastapi_cache_plus.backends.utils.ttldict.dict", + return_value=MOCKED_DICT, ): return TTLDict() @@ -45,7 +45,6 @@ def test_ser_should_rewrite_value_if_exits( key: Hashable, value: Any, rewrite_value: Any, ttl_dict: TTLDict ) -> None: ttl_dict.set(key, value) - assert ttl_dict.set(key, rewrite_value) is True assert MOCKED_DICT.get(key) == (None, rewrite_value) @@ -72,7 +71,6 @@ def test_add_should_return_false_if_key_exists( key: Hashable, value: Any, rewrite_value: Any, ttl_dict: TTLDict ) -> None: ttl_dict.add(key, value) - assert ttl_dict.add(key, rewrite_value) is False assert MOCKED_DICT.get(key) == (None, value) @@ -87,7 +85,6 @@ def test_get_should_return_value_if_exists( key: Hashable, value: Any, ttl_dict: TTLDict ) -> None: ttl_dict.set(key, value) - assert ttl_dict.get(key) == value @@ -98,7 +95,9 @@ def test_get_should_return_value_if_exists( ], ) def test_get_should_return_default_if_key_not_exists( - key: Hashable, default: Any, ttl_dict: TTLDict + key: Hashable, + default: Any, + ttl_dict: TTLDict, ) -> None: assert ttl_dict.get(key, default) == default @@ -109,17 +108,19 @@ def test_get_should_return_default_if_key_not_exists( ("hello", "world"), ], ) -def test_delete_should_remove_key(key: Hashable, value: Any, ttl_dict: TTLDict) -> None: +def test_delete_should_remove_key( + key: Hashable, + value: Any, + ttl_dict: TTLDict, +) -> None: ttl_dict.set(key, value) ttl_dict.delete(key) - assert key not in MOCKED_DICT def test_flush_should_remove_all_keys(ttl_dict: TTLDict) -> None: for num in range(10): ttl_dict.set(str(num), num) - ttl_dict.flush() assert MOCKED_DICT == {} @@ -137,7 +138,6 @@ def test_get_should_return_default_if_ttl_expired( ttl_dict: TTLDict, ) -> None: ttl_dict.set(key, value, ttl=0) - assert ttl_dict.get(key, default) == default @@ -162,10 +162,12 @@ def test_get_should_return_value_if_ttl_not_expired( ("hello", "world"), ], ) -def test_key_should_check_for_exists(keys: Tuple[Hashable], ttl_dict: TTLDict) -> None: +def test_key_should_check_for_exists( + keys: Tuple[Hashable], + ttl_dict: TTLDict, +) -> None: for key in keys: ttl_dict.set(key, key) - assert ttl_dict.exists(*keys) is True @@ -177,11 +179,13 @@ def test_key_should_check_for_exists(keys: Tuple[Hashable], ttl_dict: TTLDict) - ], ) def test_key_should_check_for_exists_with_ttl( - keys: Tuple[Hashable], ttl: int, exists: bool, ttl_dict: TTLDict + keys: Tuple[Hashable], + ttl: int, + exists: bool, + ttl_dict: TTLDict, ) -> None: for key in keys: ttl_dict.set(key, key, ttl=ttl) - assert ttl_dict.exists(*keys) is exists @@ -192,7 +196,8 @@ def test_key_should_check_for_exists_with_ttl( ], ) def test_should_return_false_if_keys_not_exist( - keys: Tuple[Hashable], ttl_dict: TTLDict + keys: Tuple[Hashable], + ttl_dict: TTLDict, ) -> None: assert ttl_dict.exists(*keys) is False @@ -205,9 +210,12 @@ def test_should_return_false_if_keys_not_exist( ], ) def test_expire_from_cache( - key: Hashable, value: Any, ttl: int, expected: Any, ttl_dict: TTLDict + key: Hashable, + value: Any, + ttl: int, + expected: Any, + ttl_dict: TTLDict, ) -> None: ttl_dict.add(key, value) ttl_dict.expire(key, ttl) - assert ttl_dict.get(key) == expected