Skip to content

[Cache] Issue in tests while creating mock for taggable cache.pool  #59193

Open
@maksym-qure4u

Description

@maksym-qure4u

Symfony version(s) affected

6.4.12

Description

I've created a cache pool with taggable adapter. I used the default one cache.adapter.redis_tag_aware. When using this in non-test mode, it works without issues. To write tests, I need to mock this, so it can be used in the workflow but without saving any data, pretty much the same as non-taggable adapter Symfony\Component\Cache\Adapter\NullAdapter.

To define taggable null adapter I used Symfony\Component\Cache\Adapter\TagAwareAdapter adapter which is initialized with Symfony\Component\Cache\Adapter\NullAdapter. To config all the services, I use .yaml file.

Issue:
When in tests my taggable pool is initialized, it's not initialized as expected with the taggable null adapter, instead it's initialized with tabbale adapter with the namespace value parameter.

How to reproduce

If I do not mock the adapter, it is initialized as expected

Config

# packages/framework.yaml
framework:
    cache:
        app: cache.adapter.redis
        default_redis_provider: provider_redis.cache
        pools:
            cache.app.redis_tags:
                public: true
                adapter: cache.adapter.redis_tag_aware
            cache.app.redis_default:
                public: true
                adapter: cache.adapter.redis

# packages/test/framework.yaml
framework:
    cache:
        app: cache.adapter.null

In the container I see these pools are initializes in the expected way

    protected static function getCache_App_RedisTagsService($container)
    {
        return $container->services['cache.app.redis_tags'] = new \Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter(
            ($container->privates['cache.app.redis_tags.recorder_inner'] ?? self::getCache_App_RedisTags_RecorderInnerService($container))
        );
    }

    protected static function getCache_App_RedisTags_RecorderInnerService($container)
    {
        $container->privates['cache.app.redis_tags.recorder_inner'] = $instance = new \Symfony\Component\Cache\Adapter\RedisTagAwareAdapter(
            ($container->services['qure4u_redis.cache'] ?? self::getQure4uRedis_CacheService($container)),
            'EnaYKcsGdl',
            0,
            ($container->privates['cache.default_marshaller'] ??= new \Symfony\Component\Cache\Marshaller\DefaultMarshaller(NULL, true))
        );
        
        return $instance;
    }

When I try to mock the cache.adapter.redis_tag_aware, the pool is initialized in the unexpected way

# framework configs are the same. I just update the services

services:
    cache.adapter.null:
        class: Symfony\Component\Cache\Adapter\NullAdapter

    cache.adapter.redis_tag_aware:
        public: true
        class: Symfony\Component\Cache\Adapter\TagAwareAdapter
        arguments:
            - '@cache.adapter.null'

Here is what I get in the container for the initialization of pool

    protected static function getCache_App_RedisTagsService($container)
    {
        return $container->services['cache.app.redis_tags'] = new \Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter(
            ($container->privates['cache.app.redis_tags.recorder_inner'] ??= new \Symfony\Component\Cache\Adapter\TagAwareAdapter('TTbbDYbUhz'))
        );
    }

Here the TagAwareAdapter is initialized as TagAwareAdapter('TTbbDYbUhz') somehow. While cache.adapter.redis_tag_aware was updated as expected with the NullAdapter

    protected static function getCache_Adapter_RedisTagAwareService($container)
    {
        return $container->services['cache.adapter.redis_tag_aware'] = new \Symfony\Component\Cache\Adapter\TagAwareAdapter(
            ($container->privates['cache.adapter.null'] ??= new \Symfony\Component\Cache\Adapter\NullAdapter())
        );
    }

When I try to overwrite the pull with another adapter, it still didn't work

# packages/test/framework.yaml
framework:
    cache:
        app: cache.adapter.null
        pools:
            cache.app.redis_tags:
                public: true
                adapter: cache.adapter.taggable.null

services:
    cache.adapter.null:
        class: Symfony\Component\Cache\Adapter\NullAdapter
        
    cache.adapter.taggable.null:
        public: true
        class: Symfony\Component\Cache\Adapter\TagAwareAdapter
        arguments:
            - '@cache.adapter.null'

In this case I still get cache pool initialized in a non-expected way, while the used adapter was initialized as expected

    protected static function getCache_App_RedisTagsService($container)
    {
        return $container->services['cache.app.redis_tags'] = new \Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter(
            ($container->privates['cache.app.redis_tags.recorder_inner'] ??= new \Symfony\Component\Cache\Adapter\TagAwareAdapter('TTbbDYbUhz'))
        );
    }

    protected static function getCache_Adapter_Taggable_NullService($container)
    {
        return $container->services['cache.adapter.taggable.null'] = new \Symfony\Component\Cache\Adapter\TagAwareAdapter(
            ($container->privates['cache.adapter.null'] ??= new \Symfony\Component\Cache\Adapter\NullAdapter())
        );
    }

Am I doing something wrong???

Possible Solution

The only solution that I finally was able to find was to redefine the cache pool in services:

# packages/test/framework.yaml
framework:
   ...

services:
    cache.app.tags:
            public: true
            class: Symfony\Component\Cache\Adapter\TagAwareAdapter
            arguments:
                - '@cache.adapter.null'

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions