fix(hook): use stable Type string key in safe_offset#270
Open
faisalahammad wants to merge 1 commit into
Open
Conversation
Functions::type() stored spl_object_hash of the Mockery Type as the processor map key. The Type is dropped after expect* registration, so PHP can recycle the hash after GC. Two expectActionAdded or expectFilterAdded calls with the same method name then collapsed to the same processor key, the second expectation overwriting the first and producing a 'should be called at least 1 times but called 0 times' Mockery failure. Switch the key to Mockery's Type::__toString() output (e.g. <Class>) in both Functions::type() and Hook::safe_offset(). Clear Hook::$objects in tearDown so type mappings do not leak across tests. Fixes 10up#268
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes: #268
Summary
WP_Mock::expectActionAdded(and the same path throughexpectFilterAddedandexpectHookAdded) failed under strict mode when the test registered two class-typed callbacks that shared a method name, for example:The second expectation silently overwrote the first, producing a Mockery failure:
Method intercepted(<Any Arguments>) should be called at least 1 times but called 0 times. Distinct method names worked by accident, andAnyInstancewas unaffected.Details
Functions::type()was storingspl_object_hash($type)as the key inHook::$objects. The Type object itself was not retained afterexpect*returned, so PHP could reclaim it. The nextMockery::type()call reused the same object handle, producing the same hash. InHook::safe_offset()the processor key for an[Type, method]array is the hash concatenated with the method name, so two different classes paired with the same method name collapsed to the same key.The fix uses Mockery's
Type::__toString()output (for example<MyClass>) as the stable key in bothFunctions::type()and theTypebranch ofHook::safe_offset().WP_Mock::tearDown()now clearsHook::$objectsso the mapping does not leak across tests.Real-instance resolution still routes through
Hook::$objects[get_class($instance)], so an actualnew SampleClass()continues to match the stable string written byFunctions::type(SampleClass::class). Closure andcallableType handling is unchanged.Introduced by #254 (1.1.0).
Contributor checklist
Testing
The reporter's reproduction and adjacent cases are added as unit tests:
tests/Unit/WP_MockTest.php::testMultipleActionsTypeSameMethod(the failing case)tests/Unit/WP_MockTest.php::testMultipleActionsTypeDistinctMethod(regression guard)tests/Unit/WP_MockTest.php::testMultipleActionsAnyInstanceSameMethod(any-instance path)tests/Unit/WP_MockTest.php::testMultipleFiltersTypeSameMethod(filter path)tests/Unit/WP_Mock/HookTest.php::testTypeSafeOffsetIsStableAcrossMultipleTypeCalls(key stability)Run locally with PHP 8.3:
composer install vendor/bin/phpunit --filter 'MultipleActionsType|MultipleFiltersType|TypeSafeOffsetIsStable' vendor/bin/phpunit vendor/bin/phpstan --memory-limit=512M vendor/bin/phpcsResults: 195 PHPUnit tests pass (one pre-existing skip in
TestCaseTest::testCanRunTests), PHPStan clean, PHPCS clean.Note:
composer test:behatcurrently fails on trunk with a pre-existing parse error infeatures/bootstrap/FunctionsContext.php. That is unrelated to this change and is not introduced here.Reviewer checklist