import hashlib import pytest from atlas_um.caching.strategies import BaseCachingStrategy from atlas_um.extensions import cache class TestCache: @pytest.fixture def test_strategy(self, faker): class TestStrategy(BaseCachingStrategy): _TEST_INVALIDATION_PATTERN = [faker.pystr()] BASE_PREFIX = faker.pystr() PREFIX_ARGS = (faker.pystr(),) PREFIX_TO_OBJECT_MAPPING = {PREFIX_ARGS[0]: faker.pystr()} @property def invalidation_patterns(self): return [self._TEST_INVALIDATION_PATTERN] return TestStrategy def test_cached_with(self, faker, app, mocker): mocked_strategy = mocker.MagicMock() mocked_cached = mocker.patch("flask_caching.Cache.cached") mocked_make_strategy_key = mocker.patch.object( cache, "_make_strategy_key" ) cache.cached_with(mocked_strategy) assert mocked_cached.called with app.test_request_context(): mocked_cached.call_args.kwargs.get("make_cache_key")( mocked_strategy ) assert mocked_make_strategy_key.call_args_list == [ mocker.call(mocked_strategy) ] def test_make_strategy_key(self, faker, app, mocker): fake_key = faker.pystr() mocked_strategy = mocker.MagicMock() mocked_strategy.return_value.key = fake_key args_as_bytes = str(()).encode() cache_key = f"/{hashlib.md5(args_as_bytes).hexdigest()}" with app.test_request_context(): result_key = cache._make_strategy_key(mocked_strategy) assert mocked_strategy.call_args_list == [mocker.call({}, cache_key)] assert result_key == fake_key def test_scan_all(self, app, mocker, faker): test_prefix = faker.pystr() test_key = faker.pystr() mocked_cache = mocker.patch("flask_caching.Cache.cache") mocked_cache._read_client.scan_iter.return_value = [ f"{test_prefix}/{test_key}".encode() ] mocked_cache.key_prefix = test_prefix res = cache.scan_all(f"*{test_key}*") assert res == [f"/{test_key}"] def test_delete_by_pattern(self, mocker, faker): test_key = faker.pystr() mocked_scan_all = mocker.patch.object(cache, "scan_all") mocked_scan_all.return_value = [test_key] mocked_delete_many = mocker.patch.object(cache, "delete_many") cache.delete_by_pattern(f"*{test_key}*") assert mocked_scan_all.call_args_list == [mocker.call(f"*{test_key}*")] assert mocked_delete_many.call_args_list == [mocker.call(test_key)] def test_invalidate_by_pattern(self, mocker, faker, test_strategy, app): test_obj = mocker.MagicMock() mocked_delete_by_pattern = mocker.patch.object( cache, "delete_by_pattern" ) cache.invalidate_related_cache(test_strategy, test_obj) assert mocked_delete_by_pattern.call_args_list == [ mocker.call(test_strategy._TEST_INVALIDATION_PATTERN) ] def test_invalidated_with(self, mocker, faker, app, test_strategy): mocked_callable = mocker.MagicMock() mocked_callable.return_value.is_right = True result = cache.invalidated_with(test_strategy)(mocked_callable)() assert result.value == mocked_callable.return_value.value