Commit 0b576c50 authored by Alexey Korepov's avatar Alexey Korepov
Browse files

Issue #3314859 by Murz: Create an example module that demonstrates the API usage and the benefits

parent 220f2ca6
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\test_helpers_example\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * Example pages to demonstrate the unit tests approach.
 */
class TestHelpersExampleController extends ControllerBase {

  /**
   * Renders a list of last articles.
   */
  public function articlesList() {
    $articlesIds = \Drupal::entityQuery('node')
      ->condition('status', 1)
      ->condition('type', 'article')
      ->sort('created', 'DESC')
      ->range(0, 3)
      ->execute();

    $articles = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadMultiple($articlesIds);

    $articlesList = [];
    foreach ($articles as $article) {
      $linkText = $article->label() . ' (' . $article->id() . ')';
      $articlesList[] = $article->toLink($linkText);
    }

    return [
      '#theme' => 'item_list',
      '#items' => $articlesList,
    ];
  }

}
+6 −0
Original line number Diff line number Diff line
name: Test Helpers Example
type: module
description: Demonstrates the benefits of using the "Test Helpers" Drupal module.
package: Custom
core: 8.x
core_version_requirement: ^8 || ^9 || ^10
+7 −0
Original line number Diff line number Diff line
test_helpers_example.page:
  path: '/test_helpers_example/page'
  defaults:
    _title: 'Test Helpers Example: list of articles'
    _controller: '\Drupal\test_helpers_example\Controller\TestHelpersExampleController::articlesList'
  requirements:
    _permission: 'access content'
+106 −0
Original line number Diff line number Diff line
<?php

namespace src\Unit;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Link;
use Drupal\node\NodeInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\test_helpers_example\Controller\TestHelpersExampleController;

/**
 * Class tests TestHelpersExampleController using a classic approach.
 *
 * @coversDefaultClass Drupal\test_helpers_example\Controller\TestHelpersExampleController
 * @group test_helpers_example
 */
class TestHelpersExampleControllerClassicTest extends UnitTestCase {

  /**
   * @covers ::articlesList
   */
  public function testArticlesList() {
    $entityQuery = $this->createMock(QueryInterface::class);
    $entityQuery->method('sort')
      ->willReturnCallback(
        function ($field, $direction = 'ASC', $langcode = NULL) use ($entityQuery) {
          $this->assertEquals('created', $field);
          $this->assertEquals('DESC', $direction);
          return $entityQuery;
        }
      );
    $entityQuery->method('range')
      ->willReturnCallback(
        function ($start = NULL, $length = NULL) use ($entityQuery) {
          $this->assertEquals(0, $start);
          $this->assertEquals(3, $length);
          return $entityQuery;
        }
      );
    $entityQuery->method('condition')
      ->willReturnCallback(
        function ($field, $value = NULL, $operator = NULL, $langcode = NULL) use ($entityQuery) {
          static $callsCount;
          if (!$callsCount) {
            $callsCount = 1;
          }
          else {
            $callsCount++;
          }
          switch ($callsCount) {
            case 1:
              $this->assertEquals('status', $field);
              $this->assertEquals(1, $value);
              $this->assertEquals(NULL, $operator);
              break;

            case 2:
              $this->assertEquals('type', $field);
              $this->assertEquals('article', $value);
              $this->assertEquals(NULL, $operator);
              break;
          }
          return $entityQuery;
        }
      );

    $entityQuery->method('execute')->willReturn(['1', '2']);

    $toLinkMock = function ($text) {
      $link = $this->createMock(Link::class);
      $link->method('getText')->willReturn($text);
      return $link;
    };

    $node1 = $this->createMock(NodeInterface::class);
    $node1->method('id')->willReturn('1');
    $node1->method('label')->willReturn('Article 1');
    $node1->method('toLink')->willReturnCallback($toLinkMock);

    $node2 = $this->createMock(NodeInterface::class);
    $node2->method('id')->willReturn('2');
    $node2->method('label')->willReturn('Article 2');
    $node2->method('toLink')->willReturnCallback($toLinkMock);

    $entityStorage = $this->createMock(EntityStorageInterface::class);
    $entityStorage->method('getQuery')->willReturn($entityQuery);
    $entityStorage->method('loadMultiple')->willReturn([$node1, $node2]);

    $entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
    $entityTypeManager->method('getStorage')->willReturn($entityStorage);

    $container = new ContainerBuilder();
    $container->set('entity_type.manager', $entityTypeManager);
    \Drupal::setContainer($container);

    $controller = new TestHelpersExampleController();
    $result = $controller->articlesList();

    $this->assertEquals('Article 1 (1)', $result['#items'][0]->getText());
    $this->assertEquals('Article 2 (2)', $result['#items'][1]->getText());
  }

}
+44 −0
Original line number Diff line number Diff line
<?php

namespace src\Unit;

use Drupal\node\Entity\Node;
use Drupal\test_helpers\UnitTestCaseWrapper;
use Drupal\test_helpers\UnitTestHelpers;
use Drupal\test_helpers_example\Controller\TestHelpersExampleController;
use Drupal\Tests\UnitTestCase;

/**
 * Class tests TestHelpersExampleController with Test Helpers API.
 *
 * @coversDefaultClass Drupal\test_helpers_example\Controller\TestHelpersExampleController
 * @group test_helpers_example
 */
class TestHelpersExampleControllerModernTest extends UnitTestCase {

  /**
   * @covers ::articlesList
   */
  public function testArticlesList() {
    ($node1 = UnitTestHelpers::createEntityStub(Node::class, ['title' => 'Article 1']))->save();
    ($node2 = UnitTestHelpers::createEntityStub(Node::class, ['title' => 'Article 2']))->save();

    UnitTestHelpers::getServiceStub('entity.query.sql')->stubAddExecuteHandler(function () use ($node1, $node2) {
      UnitTestCaseWrapper::assertTrue($this->stubCheckConditionsMatch($this->andConditionGroup()
        ->condition('status', 1)
        ->condition('type', 'article')));
      UnitTestCaseWrapper::assertTrue(UnitTestHelpers::isNestedArraySubsetOf($this->sort[0], [
        'field' => 'created',
        'direction' => 'DESC',
      ]));
      UnitTestCaseWrapper::assertEquals(['start' => 0, 'length' => 3], $this->range);
      return [$node1->id(), $node2->id()];
    });

    $result = (new TestHelpersExampleController())->articlesList();

    $this->assertEquals('Article 1 (1)', $result['#items'][0]->getText());
    $this->assertEquals('Article 2 (2)', $result['#items'][1]->getText());
  }

}
Loading