Odd behavior with TestHelpers::saveEntity() and service callbacks in setUp() method

Created on 14 September 2023, about 1 year ago
Updated 12 January 2024, 10 months ago

Problem/Motivation

Experienced an odd behavior this morning. Given the following setUp() method.

TestHelpers::service('module_handler', NULL, NULL, ['moduleExists'])
  ->method('moduleExists')->willReturnCallback(function () {
    return $this->moduleExists;
  });

TestHelpers::service('lm_utilities.routing', RoutingUtilities::class, NULL, ['getEntityFromRoute'])
  ->method('getEntityFromRoute')->willReturnCallback(function () {
    return $this->node;
  });

TestHelpers::setServices([
  'entity_type.manager' => NULL,
  'lm_utilities.form' => FormUtilities::class,
  'string_translation' => NULL,
  ]);

And the following test case.

$this->node = TestHelpers::saveEntity(Node::class, ['title' => 'Test Node', 'status' => '1']);
$hook_handler = TestHelpers::createClass(HookHandler::class);
// The method below calls RoutingUtilities::getEntityFromRoute().
$hook_handler->testBlockContentEntityBuilder();

Which results in the following error

Trying to call method getEntityTypeId() on NULL.

Further inspection shows that the mocked RoutingUtilities::getEntityFromRoute() is not picking up the correct $node value.

Known Workaround

If I move

TestHelpers::service('lm_utilities.routing', RoutingUtilities::class, NULL, ['getEntityFromRoute'])
  ->method('getEntityFromRoute')->willReturnCallback(function () {
    return $this->node;
  });

out of the setUp() method and to the test method and refactor as below

$node = TestHelpers::saveEntity(
  Node::class,
  [
    'title' => 'Test Node',
    'type' => 'test',
    'status' => '1',
  ]
);

TestHelpers::service('lm_utilities.routing', RoutingUtilities::class, TRUE, ['getEntityFromRoute'])
  ->method('getEntityFromRoute')->willReturn($node);

then the test passes as expected.

The odd thing is that the ModuleHandler::moduleExists service mock works as expected. Setting $this->moduleExists to true or false gets picked up by the mocked method callback. I'm wondering if there is a bug in TestHelpers::service() or TestHelpers::setServices() where callback functions are not getting updated values from TestHelpers::saveEntity()

πŸ’¬ Support request
Status

Closed: outdated

Version

1.2

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States j.cowher

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

Comments & Activities

  • Issue created by @j.cowher
  • πŸ‡¦πŸ‡²Armenia murz Yerevan, Armenia

    The "willReturnCallback" method sets a closure function, that works in the context of the unit test class, so $this is the TestCase class, not the service's class. This is a limitation of PHPUnit.

    But, to attach a function that will have access to the target class, you can use my trick via something like this:

    $lmUtilites = TestHelpers::service('lm_utilities.routing', RoutingUtilities::class, NULL, ['getEntityFromRoute']);
    TestHelpers::setMockedClassMethod($lmUtilites, 'getEntityFromRoute', function () {
        return $this->node;
      });
    
  • Status changed to Closed: outdated 10 months ago
  • πŸ‡¦πŸ‡²Armenia murz Yerevan, Armenia

    Closing because of the lack of response.

Production build 0.71.5 2024