I bumped into a weird entity cache invalidation issue in one of my module's test.
After my test updates a user it seems the user storage does not get invalidated automatically - only in tests, I could not reproduce this problem by executing the same actions in the UI. I think this problem is a side-effect of \Drupal::service() vs. $this->container usage in tests.
When I saw my test had started to fail then I automatically added $this->container->get('entity_type.manager')->getStorage('user')->resetCache(); call to my test to ensure user cache is empty before my test loads the user with user_load_by_mail(). Even after this forced cache clear my test still failed so I started to go deeper in code and then I realized the memory cache inside $this->container->get('entity_type.manager')->getStorage('user) is not the same as in \Drupal::service('entity_type.manager')->getStorage('user') . So basically I cleared an already empty memory cache and user_load_by_email() used a completely different storage/memory cache which has not been cleared yet.
I think when a user entity gets updated Drupal automatically invalidates the related cache entries, but what if in tests it runs the invalidation in an incorrect user storage? Or I do not know what else could explain why I have to call \Drupal::service('entity_type.manager')->getStorage('user')->resetCache(); manually.

Fun fact, the test that required this fix runs the user synchronization in the UI. There is an another test which runs the synchronization with Drush and that test does not require this fix.
| Comment | File | Size | Author |
|---|---|---|---|
| entity_storage_cache_invalidation_in_tests.png | 309.14 KB | mxr576 |
Comments
Comment #2
mxr576Comment #7
mxr576My colleague also reminded me that services (like access control handlers) with their own internal cache also works unexpectedly in kernel tests too. For example, due to access control handler's static cache property you either force-flush the cache every time when it should have been invalidated or do things like:
Comment #8
catchThis is the same issue as #2066993: Use magic methods to sync container property to \Drupal::getContainer in functional tests. $this->container can be state after a request against the tested site, but
\Drupalgets refreshed. We haven't been able to figure out a way to keep $this->container fully in sync, so the recommendation is to use\Drupaleverywhere, except that issue isn't finished yet.Comment #9
catch