Problem/Motivation

In #2795317: Allow PHPUnit 6+ support for object mocking we provided a trait so we can prepare for updating to PHPUnit 6. Whilst we still support PHPUnit 4 it would be great to make moving to PHPUnit 6 and greater simpler by not having usages in core.

Proposed resolution

  • Replace usages of getMock() with createMock() or getMockBuilder()
  • Add @trigger_error() to \Drupal\Tests\PhpunitCompatibilityTrait::getMock() we can't deprecate until PHPUnit 4 is not used because the getMockBuilder() ends up calling getMock() in PHPUnit 4. In PHPUnit 6 is calls createMock().
  • Add legacy test for calling getMock() can't deprecated

Remaining tasks

User interface changes

None

API changes

None

Data model changes

None

Comments

alexpott created an issue. See original summary.

ioana apetri’s picture

Assigned: Unassigned » ioana apetri

I am going to work on this issue.

mile23’s picture

Status: Active » Postponed

Shouldn't this issue be postponed on the outcome of #2795317: Allow PHPUnit 6+ support for object mocking ?

ioana apetri’s picture

I will continue to finish once the #2795317 is fixed.

mondrake’s picture

Status: Postponed » Active
martin107’s picture

cd core
find . -name '*Test.php' | xargs grep '\->getMock' | wc -l

shows 2280 lines where this needs changing.

To break the task into bytes sized pieces perhaps we need some structure

A issue for all the units tests,
then a issue for all the kernel tests etc?

alexpott’s picture

Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new548 KB

Patch attached replaces all calls to \Drupal\Tests\UnitTestCase::getMock() apart from in \Drupal\Tests\PhpunitCompatibilityTraitTest (as expected).

Most of the conversion was done using a replace using regex. \$this->getMock\(([^\),]+)\) using the replacement $this->getMockBuilder($1)->getMock() and then manually converting the getMock()'s which have more than one argument. If the mock was using NULL for the methods argument this has been converted into just instantiating the class. There's no point in mocking at this point because nothing is actually mocked - we're just adding a layer of complexity for no reason.

alexpott’s picture

StatusFileSize
new528.6 KB
new25.06 KB

If we want to break this up into 2 patches I guess we could do the one that is creatable via regex replace and then the one that gets the rest.

The regex just messes up:

  • core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php:492
  • core/tests/Drupal/Tests/Core/Entity/EntityUnitTest.php:178

They are simple to fix manually. Here's the 2 possible patches. Not the with args patch does not apply because of context... i.e. it needs the regex patch applied first.

The plus point for this approach is the regex patch can be reviewed with git diff --color-words

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

borisson_’s picture

Status: Needs review » Needs work

The patch no longer applies, but I agree with the approach to do as much as possible with the regex and do the rest by hand.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

lendude’s picture

Issue tags: +@deprecated, +Needs reroll

Looks like great progress already, lets get this back on the map

gábor hojtsy’s picture

Priority: Normal » Major

getMock() is the largest portion of deprecated uses in Drupal core. Drupal 8.7 currently has around 4k deprecations and over 1k is single-handedly for getMock(). Looking forward to have this in :) Upping to major for its impact.

lendude’s picture

Status: Needs work » Needs review
StatusFileSize
new26.87 KB

Here is a reroll of the 'with-args' patch, the other one we should be able to reconstruct using the regex from @alexpott

lendude’s picture

Just ran the regex and with #15 applied on top of that I added a trigger error to \Drupal\Tests\PhpunitCompatibilityTrait::getMock and ran the unit testsuite:

17x in SessionConfigurationTest::testEnforcedSessionNameViaCookieDomain from Drupal\Tests\Core\Session
17x in SessionConfigurationTest::testGeneratedSessionName from Drupal\Tests\Core\Session
16x in FieldPluginBaseTest::testRenderAsLinkWithPathAndOptions from Drupal\Tests\views\Unit\Plugin\field
15x in FieldPluginBaseTest::testRenderAsLinkWithUrlAndOptions from Drupal\Tests\views\Unit\Plugin\field
12x in CounterTest::setUp from Drupal\Tests\views\Unit\Plugin\field
11x in SessionConfigurationTest::testEnforcedCookieDomain from Drupal\Tests\Core\Session
11x in SessionConfigurationTest::testGeneratedCookieDomain from Drupal\Tests\Core\Session
9x in FieldPluginBaseTest::testRenderAsLinkWithPathAndTokens from Drupal\Tests\views\Unit\Plugin\field
9x in CommandLineOrUnsafeMethodTest::setUp from Drupal\Tests\Core\PageCache
8x in FieldPluginBaseTest::testRenderTrimmedWithMoreLinkAndPath from Drupal\Tests\views\Unit\Plugin\field
7x in SpecialAttributesRouteSubscriberTest::testOnRouteBuildingInvalidVariables from Drupal\Tests\Core\EventSubscriber
6x in RouteNormalizerRequestSubscriberTest::setUp from Drupal\Tests\redirect\Unit
6x in SessionConfigurationTest::testCookieSecureNotOverridable from Drupal\Tests\Core\Session
6x in SessionConfigurationTest::testCookieSecure from Drupal\Tests\Core\Session
6x in DomainRedirectRequestSubscriberTest::testDomainRedirect from Drupal\Tests\redirect_domain\Unit
4x in SpecialAttributesRouteSubscriberTest::testOnRouteBuildingValidVariables from Drupal\Tests\Core\EventSubscriber
4x in PhpunitCompatibilityTraitTest::testGetMock from Drupal\Tests
4x in FieldPluginBaseTest::testRenderAsExternalLinkWithPathAndTokens from Drupal\Tests\views\Unit\Plugin\field
3x in RedirectRequestSubscriberTest::testRedirectLogicWithoutQueryRetaining from Drupal\Tests\redirect\Unit
3x in RedirectRequestSubscriberTest::testRedirectLogicWithQueryRetaining from Drupal\Tests\redirect\Unit
3x in CollectRoutesTest::setUp from Drupal\Tests\rest\Unit
3x in FieldPluginBaseTest::testElementClassesWithTokens from Drupal\Tests\views\Unit\Plugin\field
3x in ViewListBuilderTest::testBuildRowEntityList from Drupal\Tests\views_ui\Unit
3x in UnitTestSuite::suite from Drupal\Tests\TestSuites
3x in MigrateSourceTest::testCount from Drupal\Tests\migrate\Unit
2x in PsrResponseSubscriberTest::testDoesNotConvertControllerResult from Drupal\Tests\Core\EventSubscriber
2x in PsrResponseSubscriberTest::setUp from Drupal\Tests\Core\EventSubscriber
2x in MigrateSourceTest::testNextNeedsUpdate from Drupal\Tests\migrate\Unit
2x in PhpunitCompatibilityTraitTest::testCreateMock from Drupal\Tests
1x in EntityDisplayModeBaseUnitTest::testSetTargetType from Drupal\Tests\Core\Config\Entity
1x in FieldPluginBaseTest::testRenderNoResult from Drupal\Tests\views\Unit\Plugin\field
1x in FieldPluginBaseTest::testGetRenderTokensWithoutArguments from Drupal\Tests\views\Unit\Plugin\field
1x in FormValidatorTest::testElementValidate from Drupal\Tests\Core\Form
1x in FormValidatorTest::testExecuteValidateHandlers from Drupal\Tests\Core\Form
1x in FieldPluginBaseTest::testGetRenderTokensWithoutFieldsAndArguments from Drupal\Tests\views\Unit\Plugin\field
1x in FieldPluginBaseTest::testRenderAsLinkWithoutPath from Drupal\Tests\views\Unit\Plugin\field
1x in FieldPluginBaseTest::testGetRenderTokensWithArguments from Drupal\Tests\views\Unit\Plugin\field
1x in ConnectionTest::testDestroy from Drupal\Tests\Core\Database
1x in EntityDisplayModeBaseUnitTest::testGetTargetType from Drupal\Tests\Core\Config\Entity
1x in MigrateSourceTest::testPrepareRowFalse from Drupal\Tests\migrate\Unit
1x in ReverseProxyMiddlewareTest::testNoProxy from Drupal\Tests\Core\StackMiddleware
1x in ViewUIObjectTest::testEntityDecoration from Drupal\Tests\views_ui\Unit
1x in PsrResponseSubscriberTest::testConvertsControllerResult from Drupal\Tests\Core\EventSubscriber
1x in ImageTest::testChmodFails from Drupal\Tests\Core\Image
1x in ImageTest::testSave from Drupal\Tests\Core\Image
1x in FieldItemListTest::testDefaultValuesFormSubmit from Drupal\Tests\Core\Field
1x in FieldItemListTest::testDefaultValuesFormValidate from Drupal\Tests\Core\Field
1x in FieldItemListTest::testDefaultValuesForm from Drupal\Tests\Core\Field
1x in AggregatorPluginSettingsBaseTest::testSettingsForm from Drupal\Tests\aggregator\Unit\Plugin
1x in MigrateSourceTest::testNewHighwater from Drupal\Tests\migrate\Unit
1x in ForumManagerTest::testGetIndex from Drupal\Tests\forum\Unit
1x in ForumListingBreadcrumbBuilderTest::testBuild from Drupal\Tests\forum\Unit\Breadcrumb
1x in ForumNodeBreadcrumbBuilderTest::testBuild from Drupal\Tests\forum\Unit\Breadcrumb
1x in MigrateSourceTest::testHighwaterTrackChangesIncompatible from Drupal\Tests\migrate\Unit
1x in MigrateSourceTest::testCountCacheKey from Drupal\Tests\migrate\Unit
1x in MigrateSourceTest::testOutdatedHighwater from Drupal\Tests\migrate\Unit
1x in ViewUIObjectTest::testIsLocked from Drupal\Tests\views_ui\Unit

So the patch in #15 needs to be extended to address those too.

martin107’s picture

Issue tags: -Needs reroll
gábor hojtsy’s picture

I wrote this above in March:

getMock() is the largest portion of deprecated uses in Drupal core. Drupal 8.7 currently has around 4k deprecations and over 1k is single-handedly for getMock(). Looking forward to have this in :) Upping to major for its impact.

The latest phpstan report from today shows 2793 errors, of those 1208 are still getmock. So close to half of all the deprecated uses. This would be quite a big step forward.

voleger’s picture

Status: Needs review » Needs work
StatusFileSize
new288.21 KB
new246.6 KB

Rerolled #15 (core/tests/Drupal/Tests/Core/Config/Entity/EntityDisplayModeBaseUnitTest.php - 2 hunks)
First iteration:
- replace generic \$this->getMock\(('[\w\\]+')\) with \$this->createMock\($1\) within core/tests folder (used replace tool of PHPStorm)
- replace generic \$this->getMock\(([\w]+::class)\) with \$this->createMock\($1\) within core/tests folder (used replace tool of PHPStorm)

voleger’s picture

StatusFileSize
new523.52 KB
new219.74 KB

Second iteration:
- replace generic \$this->getMock\(('[\w\\]+')\) with \$this->createMock\($1\) within core/modules folder (used replace tool of PHPStorm)
- replace generic \$this->getMock\(([\w]+::class)\) with \$this->createMock\($1\) within core/modules folder (used replace tool of PHPStorm)

voleger’s picture

Status: Needs work » Needs review
StatusFileSize
new525.62 KB
new3.36 KB

Third iteration:
- few manual replacements to createMock()
- few manual replacements to getMockBuilder()

Looks like this should be ready for review. Hope we didn't miss any other calls.

voleger’s picture

Actually, one call left in core/tests/Drupal/Tests/PhpunitCompatibilityTrait.php:110
but this is the overriding of the createMock method. Looks like we need to remove that method in favor of the parent createMock.

voleger’s picture

StatusFileSize
new526.89 KB
new1.14 KB

Added the deprecation error call for the getMock() method. Fixed CS issue for the @deprecated tag.

voleger’s picture

StatusFileSize
new526.9 KB
new0 bytes

Weird error in \Drupal\Tests\serialization\Unit\Normalizer\ContentEntityNormalizerTest::testSupportsNormalization() test.
There was tried to mock Drupal\Core\Entity\ConfigEntityInterface which not exists in the codebase. But with the new method call, the error was appearing. To fix this test we need to mock Drupal\Core\Config\Entity\ConfigEntityInterface which exists in the codebase.

voleger’s picture

StatusFileSize
new889 bytes

Reupload the interdiff

The last submitted patch, 21: 2929133-21.patch, failed testing. View results

voleger’s picture

StatusFileSize
new527.69 KB
new667 bytes

Added @expectedDeprecation message and @group legacy to the \Drupal\Tests\PhpunitCompatibilityTraitTest::testGetMock test.

The last submitted patch, 23: 2929133-22.patch, failed testing. View results

The last submitted patch, 24: 2929133-24.patch, failed testing. View results

voleger’s picture

StatusFileSize
new529.18 KB
new1.53 KB

Also, split up the \Drupal\Tests\PhpunitCompatibilityTraitTest::testCreateMock() test

The last submitted patch, 27: 2929133-27.patch, failed testing. View results

voleger’s picture

Assigned: ioana apetri » Unassigned

This patch contains simple deprecation calls replacement and only 1 test fix.
Wondering, is it ok to fix that test in that way? See #24 and interdiff #25

lendude’s picture

Lets not mess with the test in this issue, it would make this much harder to review (manual change in 500k of scripted stuff), I think we are addressing this in #3053417: Clean up PhpunitCompatibilityTrait so probably best wait for that to land

lendude’s picture

Status: Needs review » Reviewed & tested by the community

@alexpott pointed out that there was no need to wait, that this is fine with the test change in, so went through this with git diff --color-words, and all looks good.

+++ b/core/tests/Drupal/Tests/PhpunitCompatibilityTraitTest.php
@@ -36,4 +36,16 @@
+   * @group legacy
+   * @expectedDeprecation \Drupal\Tests\PhpunitCompatibilityTrait::getMock() is deprecated in drupal:8.5.0 and is removed from drupal:9.0.0. Use \Drupal\Tests\PhpunitCompatibilityTrait::createMock() instead. See https://www.drupal.org/node/2907725

Apparently we need both, so this is good too.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 91fe1d2 and pushed to 8.8.x. Thanks!

Let's move on :) this will be a little disruptive but we've already remove PHPUnit 4 from Drupal 8.8.x so this feels like the right moment. If we don't then this patch will enter re-roll-itis. And mostly this patch is a find-and-replace.

  • alexpott committed 91fe1d2 on 8.8.x
    Issue #2929133 by voleger, alexpott, Lendude: Replace all usages of...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

xjm’s picture

Status: Closed (fixed) » Needs work
Issue tags: +8.8.0 release notes, +Needs release note

We should mention the end of PHPUnit 4 in the release notes (along with its context of having dropped PHP 5 support entirely). Can we get a release note for that? Thanks!

xjm’s picture

Status: Needs work » Fixed
Issue tags: -8.8.0 release notes, -Needs release note

Actually, the release note is already covered by #3008870: Drop support for PHPUnit 4.8 once PHP 5 is no longer supported (8.8.x). That release note could use some work, though, so reopening it.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.