Problem/Motivation

assertAttributeEquals() is deprecated and will be removed in PHPUnit 9.

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

mondrake created an issue. See original summary.

mondrake’s picture

Status: Active » Needs review
StatusFileSize
new959 bytes

Kickoff patch, unsilencing the deprecation to see size of the changes needed.

Status: Needs review » Needs work

The last submitted patch, 2: 3126563-2.patch, failed testing. View results

mondrake’s picture

StatusFileSize
new3.71 KB

Same as #3126563-2: Replace usage of assertAttributeEquals() that is deprecated, fixing this is not trivial, since this method is checking a protected property. In latest PHPUnit philosophy (see the rather blunt comments in https://github.com/sebastianbergmann/phpunit/issues/3338), this shouldn't be the case.

So either we use Reflection, or we refactor the runtime code to provide the info we need for the test.

Here, a proposal for the database ConnectionTest.

These issues related to assertAttribute* removals are going to require lots of discussion...

mondrake’s picture

Status: Needs work » Needs review
mondrake’s picture

StatusFileSize
new614 bytes
new3.71 KB
mondrake’s picture

StatusFileSize
new2.38 KB
new6.09 KB

Two relatively simple ones to fix.

The last submitted patch, 6: 3126563-5.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 7: 3126563-6.patch, failed testing. View results

mondrake’s picture

Status: Needs work » Needs review
StatusFileSize
new7.91 KB
new38.53 KB

Something more. Sorry weird interdiff, includes other removals already committed.

mondrake’s picture

+++ b/core/modules/forum/tests/src/Unit/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php
@@ -57,18 +57,6 @@ public function testConstructor() {
-    // Reflect upon our properties, except for config which is a special case.
-    $property_names = [
-      'entityTypeManager' => $entity_type_manager,
-      'forumManager' => $forum_manager,
-      'stringTranslation' => $translation_manager,
-    ];
-    foreach ($property_names as $property_name => $property_value) {
-      $this->assertAttributeEquals(
-        $property_value, $property_name, $builder
-      );
-    }
-

I suggest just to remove this, it practically just checks service injection, seems unnecessary

Status: Needs review » Needs work

The last submitted patch, 10: 3126563-10.patch, failed testing. View results

mondrake’s picture

Status: Needs work » Needs review
StatusFileSize
new988 bytes
new7.76 KB

Here again, it seems to me that testing the injection in the constructor is irrelevant

Status: Needs review » Needs work

The last submitted patch, 13: 3126563-13.patch, failed testing. View results

mondrake’s picture

StatusFileSize
new4.14 KB
new11.93 KB

Rerolled and addressed remaining calls.

mondrake’s picture

Status: Needs work » Needs review
mondrake’s picture

StatusFileSize
new11.87 KB
new992 bytes

#15 inadvertendly reverted the change in #13.

daffie’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Database/Connection.php
    @@ -1028,6 +1036,9 @@ public function truncate($table, array $options = []) {
    +      throw new ConnectionInvalidException('Cannot access the database schema, the database connection is invalid');
    

    Throwing a new exception must be documented in the docblock

  2. Can a connection that has been destroyed, be reopened again?
  3. +++ b/core/lib/Drupal/Core/Database/Connection.php
    @@ -246,6 +253,7 @@ public static function open(array &$connection_options = []) {}
    +    $this->destroyed = TRUE;
    

    Can we remove the line of code $this->schema = NULL;. It is now not necessary any more.

  4. +++ b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php
    @@ -11,18 +11,6 @@
    -  /**
    -   * Tests the constructor.
    -   *
    -   * @covers ::__construct
    -   */
    -  public function testConstruct() {
    -    $config_factory = $this->getConfigFactoryStub(['core.menu.static_menu_link_overrides' => []]);
    -    $static_override = new StaticMenuLinkOverrides($config_factory);
    -
    -    $this->assertAttributeEquals($config_factory, 'configFactory', $static_override);
    -  }
    -
    

    Why are we removing this piece of code in this issue?

mondrake’s picture

Status: Needs work » Needs review
StatusFileSize
new12.05 KB
new626 bytes

@daffie re. #18

1. done
2. I do not think so, but one can try (theoretically) to access the schema on the destroyed connection, since it's on a public API. Once the connection is destructed, obviously, not.
3. Not really - the purpose is actually to null out the pointer to the schema object to allow garbage collection by PHP, so that's explicit.
4. Because it only seems to test the injection, which is superfluous IMO.

daffie’s picture

Status: Needs review » Needs work

@mondrake: Thank you for your explanation.

  1. +++ b/core/lib/Drupal/Core/Database/Connection.php
    @@ -246,6 +253,7 @@ public static function open(array &$connection_options = []) {}
    +    $this->destroyed = TRUE;
    

    Can you move this line next to the line $this->schema = NULL; and add some documentation why the schema must be set to NULL.

  2. +++ b/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php
    @@ -198,7 +199,9 @@ public function testDestroy() {
    -    $this->assertAttributeEquals(NULL, 'schema', $connection);
    

    Can we still keep testing with reflection that the variable $schema has the value NULL.

mondrake’s picture

Status: Needs work » Needs review
StatusFileSize
new12.55 KB
new2.93 KB

@daffie thanks

I think the method docblock of destroyis detailed enough, already. Nonetheless I made some further additions. Re. using Reflection here, it would be useless at that point since you are expecting the exception and therefore the code execution path is interrupted. Also, the entire point of dropping that method, in PHPUnit philosophy, is to reduce use of Reflection for checking internals. However, I moved the exception throing to after a check that the schema was nulled, which IMO is better since it just tests the public surface.

daffie’s picture

Status: Needs review » Needs work

I want to keep the testing for $this->schema = NULL, because it is important as you said: "the purpose is actually to null out the pointer to the schema object to allow garbage collection by PHP, so that's explicit".

As we are not removing $this->schema = NULL, the whole adding of the $destroyed parameter feels like it is out of scope for this issue. I like the functionality and that is why I am asking you to create a new issue for it.

mondrake’s picture

Status: Needs work » Needs review

@daffie you only get the exception if the value of $this->schema is null, so that's tested anyway. If we disagree, please let the issue in needs review so that someone else could comment, too.

daffie’s picture

@daffie you only get the exception if the value of $this->schema is null, so that's tested anyway. If we disagree, please let the issue in needs review so that someone else could comment, too.

Yes, we disagree and I shall leave the issue in needs review.

alexpott’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Database/Connection.php
    @@ -246,13 +253,16 @@ public static function open(array &$connection_options = []) {}
    +    $this->destroyed = TRUE;
    
    @@ -1026,9 +1036,15 @@ public function truncate($table, array $options = []) {
    +      if ($this->destroyed) {
    

    The addition of the destroyed property needs way more work. Imo we need to evaluate the destroy method and move this code to __destruct() so the object is always destructed correctly. We need to look at #843114: DatabaseConnection::__construct() and DatabaseConnection_mysql::__construct() leaks $this (Too many connections) and work out why this solution was chosen.

  2. +++ b/core/tests/Drupal/Tests/Core/Database/ConnectionTest.php
    @@ -198,7 +199,9 @@ public function testDestroy() {
    -    $this->assertAttributeEquals(NULL, 'schema', $connection);
    +    $this->expectException(ConnectionInvalidException::class);
    +    $this->expectExceptionMessage('Cannot access the database schema, the database connection is being closed');
    +    $connection->schema();
    

    I think using reflection here is preferable. And not changing runtime code for testability reasons.

  3. +++ b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php
    @@ -11,18 +11,6 @@
    -  /**
    -   * Tests the constructor.
    -   *
    -   * @covers ::__construct
    -   */
    -  public function testConstruct() {
    -    $config_factory = $this->getConfigFactoryStub(['core.menu.static_menu_link_overrides' => []]);
    -    $static_override = new StaticMenuLinkOverrides($config_factory);
    -
    -    $this->assertAttributeEquals($config_factory, 'configFactory', $static_override);
    -  }
    

    +1 this test is not a test.

mondrake’s picture

Assigned: Unassigned » mondrake

OK. Let's revise destroy separately.

alexpott’s picture

mondrake’s picture

Assigned: mondrake » Unassigned
Status: Needs work » Needs review
StatusFileSize
new3.57 KB
new9.56 KB

Addressed #20 and #25.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

All changes look good to me.
The suppression of warnings for the use of assertAttributeEquals() is removed.
All instances of assertAttributeEquals() are removed.
For me it is RTBC.

mondrake’s picture

+++ b/core/modules/block/tests/modules/block_test/src/PluginForm/EmptyBlockForm.php
@@ -24,4 +24,14 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
+  /**
+   * Returns the plugin connected with the form.
+   *
+   * @return \Drupal\Component\Plugin\PluginInspectionInterface
+   *   The plugin connected with the form.
+   */
+  public function getPlugin() {
+    return $this->plugin;
+  }
+
 }
+++ b/core/modules/migrate/tests/src/Unit/TestSqlIdMap.php
@@ -41,6 +41,16 @@ public function getDatabase() {
+  /**
+   * Returns the value of the $message property.
+   *
+   * @return \Drupal\migrate\MigrateMessageInterface
+   *   The message.
+   */
+  public function getMessage() {
+    return $this->message;
+  }
+
+++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeManagerTest.php
@@ -519,6 +518,16 @@ public static function create(ContainerInterface $container) {
+  /**
+   * Returns the value of the $color property.
+   *
+   * @return string
+   *   The value of the color property.
+   */
+  public function getColor() {
+    return $this->color;
+  }
+

I wonder whether we shoud use public methods instead of getters like in a previous similar case

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

@mondrake good idea - less boilerplate and it's all test code so getters have no value.

mondrake’s picture

Status: Needs work » Needs review
StatusFileSize
new9.25 KB
new4.14 KB
longwave’s picture

Status: Needs review » Reviewed & tested by the community

The only changes are in tests or test implementations, the changes are as minimal as possible and follow what we did in recent similar issues, I think this is ready to go in.

alexpott’s picture

Version: 9.1.x-dev » 9.0.x-dev
Status: Reviewed & tested by the community » Fixed

Committed and pushed a6e402fc01 to 9.1.x and 50a6075593 to 9.0.x. Thanks!

  • alexpott committed a6e402f on 9.1.x
    Issue #3126563 by mondrake, daffie, alexpott: Replace usage of...

  • alexpott committed 50a6075 on 9.0.x
    Issue #3126563 by mondrake, daffie, alexpott: Replace usage of...
mondrake’s picture

Thank you all for your reviews.

Status: Fixed » Closed (fixed)

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