codekandis/phpunit

`codekandis/phpunit` is a library for `PHPUnit` testing with enhanced test cases and custom constraint assertions.

Maintainers

Package info

github.com/codekandis/phpunit

Documentation

pkg:composer/codekandis/phpunit

Statistics

Installs: 592

Dependents: 32

Suggesters: 0

Stars: 0

Open Issues: 0

5.0.5 2026-06-15 07:53 UTC

This package is auto-updated.

Last update: 2026-06-15 07:55:02 UTC


README

Version License Minimum PHP Version Code Coverage

codekandis/phpunit is a library for PHPUnit testing with enhanced test cases and custom constraint assertions.

Index

Installation

Install the latest version with

$ composer require --dev codekandis/phpunit

Usage

Using the test case wrapper

Create a test case that extends the TestCase wrapper.

The additional constraint assertions are available through this wrapper.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;

class ApplicationTest extends TestCase
{
}

Failing exception test branches

Use the protected fail helpers in test cases that assert exception control flow explicitly.

TestCase::failUnexpectedThrowableHasBeenThrown()

Use TestCase::failUnexpectedThrowableHasBeenThrown() to fail a test when a throwable has been thrown in a branch that must not throw.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;
use Throwable;

final class ServiceTest extends TestCase
{
	public function testIfServiceRunsWithoutThrowable(): void
	{
		try
		{
			$service = new Service();
			$service->run();
		}
		catch ( Throwable $throwable )
		{
			static::failUnexpectedThrowableHasBeenThrown( $throwable::class );
		}

		static::assertTrue( $service->hasRun() );
	}
}

TestCase::failExpectedThrowableHasNotBeenThrown()

Use TestCase::failExpectedThrowableHasNotBeenThrown() to fail a test when an expected throwable has not been thrown.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;
use RuntimeException;

final class ServiceTest extends TestCase
{
	public function testIfServiceThrowsRuntimeException(): void
	{
		try
		{
			$service = new Service();
			$service->fail();
		}
		catch ( RuntimeException $throwable )
		{
			static::assertSame( 'The service failed.', $throwable->getMessage() );

			return;
		}

		static::failExpectedThrowableHasNotBeenThrown( RuntimeException::class );
	}
}

Using the data provider interface

Create a data provider that implements DataProviderInterface.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\DataProviderInterface;
use Override;

final class DifferentValuesDataProvider implements DataProviderInterface
{
	#[Override]
	public static function provideData(): iterable
	{
		return [
			0 => [
				23,
				42
			],
			1 => [
				'foo',
				'bar'
			]
		];
	}
}

Use the data provider in your test case through DataProviderInterface::PROVIDER_METHOD_NAME.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;
use CodeKandis\PhpUnit\DataProviderInterface;
use PHPUnit\Framework\Attributes\DataProviderExternal;

final class DifferentValuesTest extends TestCase
{
	#[DataProviderExternal( DifferentValuesDataProvider::class, DataProviderInterface::PROVIDER_METHOD_NAME )]
	public function testValuesAreDifferent( mixed $value1, mixed $value2 ): void
	{
		static::assertNotSame( $value1, $value2 );
	}
}

Asserting array subsets

TestCase::assertArrayContainsKeyedSubset()

Use TestCase::assertArrayContainsKeyedSubset() to assert that $actualArray contains $expectedSubset with matching keys and values. Set $strict to true to compare values strictly, or to false to compare values loosely.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;

final class ArrayTest extends TestCase
{
	public function testArrayContainsKeyedSubset(): void
	{
		static::assertArrayContainsKeyedSubset(
			[
				'foo' => [
					'bar' => 23
				]
			],
			[
				'foo' => [
					'bar' => 23,
					'baz' => 42
				]
			],
			true
		);
	}
}

TestCase::assertArrayContainsUnkeyedSubset()

Use TestCase::assertArrayContainsUnkeyedSubset() to assert that $actualArray contains the values of $expectedSubset without comparing keys. Set $strict to true to compare values strictly, or to false to compare values loosely.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;

final class ArrayTest extends TestCase
{
	public function testArrayContainsUnkeyedSubset(): void
	{
		static::assertArrayContainsUnkeyedSubset(
			[
				23,
			],
			[
				42,
				23
			],
			true
		);
	}
}

TestCase::assertIsKeyedSubsetOfArray()

Use TestCase::assertIsKeyedSubsetOfArray() to assert that $actualSubset is contained in $expectedArray with matching keys and values. Set $strict to true to compare values strictly, or to false to compare values loosely.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;

final class ArrayTest extends TestCase
{
	public function testKeyedSubsetIsSubsetOfArray(): void
	{
		static::assertIsKeyedSubsetOfArray(
			[
				'foo' => [
					'bar' => 23,
					'baz' => 42
				]
			],
			[
				'foo' => [
					'bar' => 23
				]
			],
			true
		);
	}
}

TestCase::assertIsUnkeyedSubsetOfArray()

Use TestCase::assertIsUnkeyedSubsetOfArray() to assert that the values of $actualSubset are contained in $expectedArray without comparing keys. Set $strict to true to compare values strictly, or to false to compare values loosely.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;

final class ArrayTest extends TestCase
{
	public function testUnkeyedSubsetIsSubsetOfArray(): void
	{
		static::assertIsUnkeyedSubsetOfArray(
			[
				42,
				23
			],
			[
				23
			],
			true
		);
	}
}

Asserting subclass relationships

TestCase::assertIsSubClassOf()

Use TestCase::assertIsSubClassOf() to assert that $actual is a subclass of or implements $expectedInterfaceOrClassFqcn. $actual can be an object or an FQCN.

<?php declare( strict_types = 1 );
namespace Vendor\Project\Tests;

use CodeKandis\PhpUnit\TestCase;

interface MessageHandlerInterface
{
}

final class MessageHandler implements MessageHandlerInterface
{
}

final class MessageHandlerTest extends TestCase
{
	public function testMessageHandlerImplementsMessageHandlerInterface(): void
	{
		static::assertIsSubClassOf(
			MessageHandlerInterface::class,
			MessageHandler::class
		);
	}
}

The assertion throws an UnknownClassOrInterfaceException if the expected type does not exist.