mcpField
D
drupal-unit

drupal-unit

github.com/edutrulTesting & quality7351 installsUpdated 21w ago
Repository

About drupal-unit

A Drupal unit-testing reference for PHP developers testing logic that does not depend on Drupal runtime services. It shows PHPUnit mocking patterns and commands for running module tests.

Key features

  1. 01Choosing unit tests for pure PHP
  2. 02PHPUnit mock examples
  3. 03Mocking Drupal translation
  4. 04Mocking logger expectations
  5. 05Commands for running module tests

Use cases

  1. 01Testing utility functions and transformations
  2. 02Testing classes with mocked dependencies
  3. 03Checking expected logger messages
  4. 04Running one module's unit test suite

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/edutrul/drupal-ai --skill drupal-unit

After installing, type/drupal-unitin Claude Code to confirm it loaded.

Bundled filesREADME.md

Details

From the project README

Drupal Unit Tests

When to Use

  • Pure PHP logic with no Drupal dependencies
  • Utility functions, data transformations, value objects
  • Classes where all dependencies can be mocked

Basic Structure

// tests/src/Unit/MyServiceTest.php
namespace Drupal\Tests\my_module\Unit;

use Drupal\Tests\UnitTestCase;
use Drupal\my_module\Service\MyService;
use Psr\Log\LoggerInterface;

/**
 * @coversDefaultClass \Drupal\my_module\Service\MyService
 * @group my_module
 */
final class MyServiceTest extends UnitTestCase {

  private MyService $service;

  protected function setUp(): void {
    parent::setUp();

    $logger = $this->createMock(LoggerInterface::class);
    $this->service = new MyService($logger);
  }

  /**
   * @covers ::processData
   */
  public function testProcessData(): void {
    $input = ['foo' => 'bar'];
    $result = $this->service->processData($input);

    $this->assertArrayHasKey('processed', $result);
    $this->assertTrue($result['processed']);
  }

  /**
   * @covers ::processData
   */
  public function testProcessDataWithEmptyInput(): void {
    $this->expectException(\InvalidArgumentException::class);
    $this->service->processData([]);
  }

}

Mocking with PHPUnit

// Mock a simple interface
$mock = $this->createMock(SomeInterface::class);
$mock->method('someMethod')->willReturn('value');

// Mock with argument matching
$mock->expects($this->once())
  ->method('someMethod')
  ->with($this->equalTo('expected-arg'))
  ->willReturn('result');

// Mock throwing exception
$mock->method('someMethod')->willThrowException(new \RuntimeException('Error'));

// Stub multiple calls
$mock->method('someMethod')
  ->willReturnMap([
    ['arg1', 'result1'],
    ['arg2', 'result2'],
  ]);

Mocking Drupal Translation (t())

// UnitTestCase provides getStringTranslationStub()
$this->service = new MyService(
  $this->getStringTranslationStub()
);

Mocking Logger

// Expect a specific log message
$logger = $this->createMock(LoggerInterface::class);
$logger->expects($this->once())
  ->method('error')
  ->with($this->stringContains('Failed to process'));

Running Tests

Examples assume a docroot/-based Drupal project. If your project uses web/ or another document root, adjust paths accordingly.

# Run specific test file
ddev exec vendor/bin/phpunit docroot/modules/custom/my_module/tests/src/Unit/MyServiceTest.php

# Run all unit tests for a module
ddev exec vendor/bin/phpunit docroot/modules/custom/my_module/tests/src/Unit/

# Run with verbose output
ddev exec vendor/bin/phpunit --verbose docroot/modules/custom/my_module/tests/

Comments

Markdown supported