Call to undefined method MetadataBag::getMasquerade() at MasqueradeCacheContext.php line 31

Created on 22 August 2024, 3 months ago
Updated 3 September 2024, 3 months ago

Problem/Motivation

We have some custom internal tests implemented for phpunit. And after upgrading to v8.x-2.0 we have following error message for every test (right before phpunit output):
Uncaught PHP Exception Error: "Call to undefined method Symfony\Component\HttpFoundation\Session\Storage\MetadataBag::getMasquerade()" at /www/tws.mt.test/web/modules/contrib/masquerade/src/Cache/MasqueradeCacheContext.php line 31

I suppose this is because module expects $bag to be \Drupal\masquerade\Session\MetadataBag and actual one is Symfony\Component\HttpFoundation\Session\Storage\MetadataBag for some reasons.

Simple solutions is to check if getMasquerade() method exists before calling. This approach solved problem for us.

🐛 Bug report
Status

Needs review

Version

2.0

Component

Code

Created by

🇧🇾Belarus f1mishutka Minsk

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @f1mishutka
  • Issue was unassigned.
  • Status changed to Needs review 3 months ago
  • 🇧🇾Belarus f1mishutka Minsk

    Added MR with simple solution for this problem

  • Pipeline finished with Success
    3 months ago
    Total: 164s
    #261706
  • Status changed to Needs work 3 months ago
  • 🇫🇷France andypost

    Curious why the bag is different but better replace check for bag classname

  • Pipeline finished with Success
    3 months ago
    Total: 197s
    #261898
  • Status changed to Needs review 3 months ago
  • 🇧🇾Belarus f1mishutka Minsk

    Curious why the bag is different

    This is hidden somewhere deep in Drupal core I think. We do bootstrap Drupal core with custom code (similar to index.php) for bunch of our specific integrational tests. So I did not dig to deep about masquerade and core interaction :)

    better replace check for bag classname

    Done: check replaced to instanceof.

  • Pipeline finished with Success
    3 months ago
    Total: 165s
    #264607
  • 🇧🇾Belarus f1mishutka Minsk

    Any chance to have this merged at least to -dev branch?
    Thanks.

  • 🇦🇺Australia mstrelan

    Experiencing the same issue with Drupal Test Traits, the MR fixes it.

  • 🇦🇺Australia acbramley

    Would be good to get this committed, nice n simple fix.

  • 🇫🇷France andypost

    This simple fix points out to bugs in tests because this check means that service is not decorated, moreover all other parts of code supposing that metadatabag is decorated and then it should be fixed in all places

    So instead of "wont't fix" I wanna get more opinions why unit tests should be able to partially mock functionality?
    See masquerade.services.yml

      masquerade.session_manager.metadata_bag:
        class: Drupal\masquerade\Session\MetadataBag
        decorates: session_manager.metadata_bag
        parent: session_manager.metadata_bag
        public: false
    
  • 🇦🇺Australia mstrelan

    I did some digging, and while I don't have any answers I do have some further information.

    The test that was triggering the error looks like this:

    $this->setCurrentUser($this->createUser()->addRole('regional_manager'));
    $url = Url::fromRoute('my_module.my_route');
    $request = Request::create($url->toString(), 'HEAD');
    $response = \Drupal::service('http_kernel')->handle($request);
    

    But if I change this to use ::drupalLogin and ::drupalGet then the bag is decorated correctly.

    Similarly, If I remove the access toolbar permission from the role and revert to the original test, then MasqueradeCacheContext::getContext does not get invoked and the test passes.

    Finally, if I remove the masquerade_switch_back item from masquerade_toolbar then again the test passes.

    Hopefully that helps to explain this.

Production build 0.71.5 2024