0

I have been tasked with writing a Unit Test for a method where I pass in a Node object, modify an Entity Reference field value, and then return a Node object.

Since this is a Unit test, I am unsure as to how to write an assertion.

Note: just included relevant code.

class ClassIAmTesting {
    public function populateSymbols(Node $node) {

      $node->field_symbols->appendItem(['target_id' => $symbol_id]);
      return $node;
    }
}

I have created a mock for the Entity Reference Field:

$entityReferenceMock = $this->getMockBuilder(EntityReferenceFieldItemList::class)
      ->disableOriginalConstructor()
      ->setMethods(['appendItem'])
      ->getMock();

I have also created a mock of the Node Object

$nodeMock = $this->getMockBuilder(Node::class)
      ->disableOriginalConstructor()
      ->getMock();

$nodeMock->expects($this->any)
      ->method('__get')
      ->with('field_symbols_in_this_story')
      ->willReturn($entityReferenceMock);

The method returns a Node object but how can I assert that the Entity Reference Field Value has changed?

Edit: The class with more details:

class ClassIAmTesting {
  public function populateSymbols(Node $node) {

    $body = $node->field_body->value;

    $dom = Html::load($body);
    $xpath = new \DOMXPath($dom);

    foreach ($xpath->query('//span[@class="tooltip"]') as $xpathNode) {

      $symbol_id = $xpathNode->getAttribute('data-symbol');

      $node->field_symbols->appendItem(['target_id' => $symbol_id]);
    }

    return $node;
  }
}
  • 1
    EntityReferenceFieldItemList already has tests to assert its values have changed. What's the value in this test? The method is essentially pass in node, get node back. So if you trust core tests, then you can either spy on the appendItem method (using prophecy instead of phpunit mock objects) and the test fails if it's not called correctly. Not sure if questions about phpunit or prophecy are on-topic... – mradcliffe Jan 8 at 18:25
  • Hi @mradcliffe thanks for the response. I edited the end of my question to include more of the example class. There is a foreach loop. It looks for data-symbol attributes from the body field and extracts the IDs. Each ID that is extracted is appended to the Entity Reference Field. – AndrewMRiv Jan 8 at 19:34
0

This is a good example of a test that would probably be better suited as a kernel test rather than a unit test since it's dealing with the Field API which can get tricky to mock, and is probably better to test with the real thing.

To test this as a kernel test you need to ensure the following:

  • Either create your field field_symbols directly in the test's setUp method or place the field config and storage YAML files in a module's config/install directory, and enable that module for the test.
    • You'll need to also enable the node module, and any other module's that your code depends on

Then, in your test you can execute the custom code and ensure the expected values are set:

public function testFieldSymbols() {
  $node = $this->createNode();

   // Do this, or retrieve the service if your class is a service.
   $fixture = new ClassIAmTesting();

   $fixture->populateSymbols($node);

   $this->assertEquals('expected field value', $node->field_symbols->target_id);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.