Problem/Motivation

ContentEntityInterface::set() documents that $this is returned from the method.

ContentEntityBase::set(), however, does not return anything.

Proposed resolution

  • Add return $this; to the end of ContentEntityBase::set()
  • Add a testSet() to ContentEntityBaseUnitTest which calls the set() method and asserts that $this is returned

Remaining tasks

  1. Review patch
  2. Commit

User interface changes

None.

API changes

None.

Comments

tstoeckler’s picture

banviktor’s picture

Assigned: Unassigned » banviktor
Issue summary: View changes

I agree it doesn't match the documentation.
Added link for documentation in the issue summary.

banviktor’s picture

Issue summary: View changes
banviktor’s picture

Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new1.78 KB

I have uploaded a patch for the issue

tstoeckler’s picture

Issue tags: -Needs tests

Awesome that you wrote a test, thanks!

I looked at how the rest of the tests in that class are implemented and I noticed that we can simplify the test I think.

+++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php
@@ -524,4 +524,32 @@ public function testGetFields($expected, $include_computed, $is_computed, $field
+    //Mock ContentEntityBase
+    $mock_base = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityBase')
+      ->disableOriginalConstructor()
+      ->setMethods(array('get', 'getTranslatedField'))
+      ->getMockForAbstractClass();
+
+    //Mock FieldItemInterface
+    $mock_field = $this->getMockBuilder('Drupal\Core\Field\FieldItemInterface')
+      ->disableOriginalConstructor()
+      ->setMethods(array('setValue'))
+      ->getMockForAbstractClass();
+
+    //Set up expectations for get(), it returns the mocked FieldItemInterface
+    $mock_base->expects($this->any())
+      ->method('get')
+      ->willReturn($mock_field);
+
+    //Exercise set(), check if it returns $this
+    $this->assertSame(
+      $mock_base,
+      $mock_base->set(null, null)
+    );

ContentEntityBaseUnitTest already has a $this->entity which gets prepared in setUp() which you can use directly.

So the test could be written as

$this->assertSame($this->entity, $this->entity->set('id'));

or similar.

banviktor’s picture

I've tried that way, but set() calls get() first which needs a lot of things that isn't valid in $this->entity, and results in error. I could use $this->entity but can't avoid creating a mocked FieldItemInterface for mocking the get()'s return value.
Should I rewrite the test so that it uses $this->entity instead of $mock_base?

banviktor’s picture

I have to update it anyway cause the version I uploaded don't even need the mock for ContentEntityBase's getTranslatedField.

banviktor’s picture

I've fixed the getTranslatedField issue, but not sure how I could use $this->entity. It's created with getMockForAbstractClass() and I can't mock get() afterwards as it's not an abstract method.

tstoeckler’s picture

Status: Needs review » Needs work
Issue tags: -Novice

Yes, you are completely right. Sorry, I thought I had seen some existing usage of $this->entity->set() but that was in a different test class. Sorry, stupid me.

ContentEntityBaseUnitTest is already pretty weird in that it's more of an integration test, but I still think it makes sense to align this more with the current code. I.e. in theory I think your code is preferred (because it's an actual unit test) but it's not inline with the rest of the class.

So I played around a bit and the following seems to work:
Add

    $this->fieldTypePluginManager->expects($this->any())
      ->method('createFieldItemList')
      ->will($this->returnValue($this->getMock('Drupal\Core\Field\FieldItemListInterface')));

in setUp() where $this->fieldTypePluginManager is being set up.

Then my above sample code should work (but for the fact that I forgot the second required argument).

Can you try that @banviktor?

Removing the Novice tag, this is getting a bit convoluted... :-)

banviktor’s picture

Great idea!
Implemented, tested, uploaded.

tstoeckler’s picture

Status: Needs work » Reviewed & tested by the community

Awesome, this looks great to me.

+    //Exercise set(), check if it returns $this

@banvikor: Our coding standards dictate that there's an empty space between the "//" and the begining of the sentence.

I'm hoping that can be fixed on commit, so marking RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue is a normal bug fix, and doesn't include any disruptive changes, so it is allowed per https://www.drupal.org/core/beta-changes. Committed 5a58ba9 and pushed to 8.0.x. Thanks!

  • alexpott committed 5a58ba9 on 8.0.x
    Issue #2449709 by banviktor: ContentEntityBase::set() does not respect...
tstoeckler’s picture

Awesome work @banviktor, welcome to the team! :-)

Status: Fixed » Closed (fixed)

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