feat(bridge-rector): convert PHPUnit mocks onto the Double bridge - #333
Open
roxblnfk wants to merge 1 commit into
Open
feat(bridge-rector): convert PHPUnit mocks onto the Double bridge#333roxblnfk wants to merge 1 commit into
roxblnfk wants to merge 1 commit into
Conversation
CreateMockToDoubleRector turns createMock/createStub and their expects()/method()/will*() chains into \JMac\Testing\Double calls, now that testo/bridge-double supplies the target API the stub rule was written without. The invocation matcher moves onto the verb (any→allows, else expects + times()/never()), the method name onto expects('m')/allows('m'), and the return verbs onto returns/throws/resolves.
The chain is rebuilt at statement level, not per call: an unmappable link (willReturnMap, willReturnSelf, a variable matcher, with() constraint objects, getMockBuilder, prophesize) leaves the whole statement untouched instead of the inner expects()->method() being rewritten on its own. The MockToTestoRector stub, FEATURE_PARITY.md, TODO.md and the migrate-from-phpunit skill are narrowed to those residual manual forms.
Assisted-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
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.
🔍 What was changed
CreateMockToDoubleRector(PHPUnit → Testo set): converts PHPUnit mocks/stubs onto the Double bridge (testo/bridge-double), which is the target API the oldMockToTestoRectorstub was written without.$this->createMock(X)/$this->createStub(X)→\JMac\Testing\Double::for(X).any→allows, everything else keepsexpectsand folds intotimes()/never()—once→times(1),exactly→times,atLeastOnce/atLeast/atMost→times(minimum:/maximum:)), the method name moves off->method('m')ontoexpects('m')/allows('m'), and returns mapwillReturn/willReturnOnConsecutiveCalls→returns,willThrowException→throws,willReturnCallback→resolves(plus the legacywill($this->returnValue()/throwException()/returnCallback())wrappers).MockToTestoRectorstub,FEATURE_PARITY.md,TODO.mdand the migrate-from-phpunit skill to the residual manual forms (getMockBuilder,prophesize,willReturnMap/willReturnSelf/willReturnArgument, variable matcher,with()constraint objects).How it works
Expression), thecreateMock/createStubrewrite at call level (MethodCall).expects()->method()is never rewritten on its own.expects('m')with a string argument, Double return verbs) does not re-trigger on a later pass.Why?
The Double bridge gave mocks a faithful Testo target for the first time, so the mock row moves from ⛔ to a documented 🟡. Argument constraints inside
with()are passed through untouched — a literal expected value converts cleanly, a constraint object does not and stays manual.Review notes
Rector 2 exposes no parent-node attribute to rules (
AttributeKey::PARENT_NODEis gone), so "am I the outermost call of the chain?" can't be asked at call level — a call-level rebuild converts the inner sub-chain of an otherwise-unconvertible statement. Anchoring the rebuild on theExpressionstatement instead is what makes the conversion all-or-nothing.Checklist
method(), legacywill(), inline factory+chain, and two left-unchanged cases (unsupported link, non-mock chain). Full Rector bridge suite green (204 tests).