*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework;
use function class_exists;
use function count;
use function file_get_contents;
use function interface_exists;
use function is_bool;
use ArrayAccess;
use Countable;
use Generator;
use PHPUnit\Event;
use PHPUnit\Framework\Constraint\ArrayHasKey;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\Constraint\Constraint;
use PHPUnit\Framework\Constraint\Count;
use PHPUnit\Framework\Constraint\DirectoryExists;
use PHPUnit\Framework\Constraint\FileExists;
use PHPUnit\Framework\Constraint\GreaterThan;
use PHPUnit\Framework\Constraint\IsAnything;
use PHPUnit\Framework\Constraint\IsEmpty;
use PHPUnit\Framework\Constraint\IsEqual;
use PHPUnit\Framework\Constraint\IsEqualCanonicalizing;
use PHPUnit\Framework\Constraint\IsEqualIgnoringCase;
use PHPUnit\Framework\Constraint\IsEqualWithDelta;
use PHPUnit\Framework\Constraint\IsFalse;
use PHPUnit\Framework\Constraint\IsFinite;
use PHPUnit\Framework\Constraint\IsIdentical;
use PHPUnit\Framework\Constraint\IsInfinite;
use PHPUnit\Framework\Constraint\IsInstanceOf;
use PHPUnit\Framework\Constraint\IsJson;
use PHPUnit\Framework\Constraint\IsList;
use PHPUnit\Framework\Constraint\IsNan;
use PHPUnit\Framework\Constraint\IsNull;
use PHPUnit\Framework\Constraint\IsReadable;
use PHPUnit\Framework\Constraint\IsTrue;
use PHPUnit\Framework\Constraint\IsType;
use PHPUnit\Framework\Constraint\IsWritable;
use PHPUnit\Framework\Constraint\JsonMatches;
use PHPUnit\Framework\Constraint\LessThan;
use PHPUnit\Framework\Constraint\LogicalAnd;
use PHPUnit\Framework\Constraint\LogicalNot;
use PHPUnit\Framework\Constraint\LogicalOr;
use PHPUnit\Framework\Constraint\LogicalXor;
use PHPUnit\Framework\Constraint\ObjectEquals;
use PHPUnit\Framework\Constraint\ObjectHasProperty;
use PHPUnit\Framework\Constraint\RegularExpression;
use PHPUnit\Framework\Constraint\SameSize;
use PHPUnit\Framework\Constraint\StringContains;
use PHPUnit\Framework\Constraint\StringEndsWith;
use PHPUnit\Framework\Constraint\StringEqualsStringIgnoringLineEndings;
use PHPUnit\Framework\Constraint\StringMatchesFormatDescription;
use PHPUnit\Framework\Constraint\StringStartsWith;
use PHPUnit\Framework\Constraint\TraversableContainsEqual;
use PHPUnit\Framework\Constraint\TraversableContainsIdentical;
use PHPUnit\Framework\Constraint\TraversableContainsOnly;
use PHPUnit\Util\Xml\Loader as XmlLoader;
use PHPUnit\Util\Xml\XmlException;
/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
abstract class Assert
{
private static int $count = 0;
/**
* Asserts that an array has a specified key.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertArrayHasKey(mixed $key, array|ArrayAccess $array, string $message = ''): void
{
$constraint = new ArrayHasKey($key);
static::assertThat($array, $constraint, $message);
}
/**
* Asserts that an array does not have a specified key.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertArrayNotHasKey(mixed $key, array|ArrayAccess $array, string $message = ''): void
{
$constraint = new LogicalNot(
new ArrayHasKey($key),
);
static::assertThat($array, $constraint, $message);
}
/**
* @throws ExpectationFailedException
*/
final public static function assertIsList(mixed $array, string $message = ''): void
{
static::assertThat(
$array,
new IsList,
$message,
);
}
/**
* Asserts that a haystack contains a needle.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertContains(mixed $needle, iterable $haystack, string $message = ''): void
{
$constraint = new TraversableContainsIdentical($needle);
static::assertThat($haystack, $constraint, $message);
}
/**
* @throws ExpectationFailedException
*/
final public static function assertContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void
{
$constraint = new TraversableContainsEqual($needle);
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that a haystack does not contain a needle.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertNotContains(mixed $needle, iterable $haystack, string $message = ''): void
{
$constraint = new LogicalNot(
new TraversableContainsIdentical($needle),
);
static::assertThat($haystack, $constraint, $message);
}
/**
* @throws ExpectationFailedException
*/
final public static function assertNotContainsEquals(mixed $needle, iterable $haystack, string $message = ''): void
{
$constraint = new LogicalNot(new TraversableContainsEqual($needle));
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that a haystack contains only values of a given type.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
{
if ($isNativeType === null) {
$isNativeType = self::isNativeType($type);
}
static::assertThat(
$haystack,
new TraversableContainsOnly(
$type,
$isNativeType,
),
$message,
);
}
/**
* Asserts that a haystack contains only instances of a given class name.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertContainsOnlyInstancesOf(string $className, iterable $haystack, string $message = ''): void
{
static::assertThat(
$haystack,
new TraversableContainsOnly(
$className,
false,
),
$message,
);
}
/**
* Asserts that a haystack does not contain only values of a given type.
*
* @throws Exception
* @throws ExpectationFailedException
*/
final public static function assertNotContainsOnly(string $type, iterable $haystack, ?bool $isNativeType = null, string $message = ''): void
{
if ($isNativeType === null) {
$isNativeType = self::isNativeType($type);
}
static::assertThat(
$haystack,
new LogicalNot(
new TraversableContainsOnly(
$type,
$isNativeType,
),
),
$message,
);
}
/**
* Asserts the number of elements of an array, Countable or Traversable.
*
* @throws Exception
* @throws ExpectationFailedException
* @throws GeneratorNotSupportedException
*/
final public static function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void
{
if ($haystack instanceof Generator) {
throw GeneratorNotSupportedException::fromParameterName('$haystack');
}
static::assertThat(
$haystack,
new Count($expectedCount),
$message,
);
}
/**
* Asserts the number of elements of an array, Countable or Traversable.
*
* @throws Exception
* @throws ExpectationFailedException
* @throws GeneratorNotSupportedException
*/
final public static function assertNotCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void
{
if ($haystack instanceof Generator) {
throw GeneratorNotSupportedException::fromParameterName('$haystack');
}
$constraint = new LogicalNot(
new Count($expectedCount),
);
static::assertThat($haystack, $constraint, $message);
}
/**
* Asserts that two variables are equal.
*
* @throws ExpectationFailedException
*/
final public static function assertEquals(mixed $expected, mixed $actual, string $message = ''): void
{
$constraint = new IsEqual($expected);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are equal (canonicalizing).
*
* @throws ExpectationFailedException
*/
final public static function assertEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void
{
$constraint = new IsEqualCanonicalizing($expected);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are equal (ignoring case).
*
* @throws ExpectationFailedException
*/
final public static function assertEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void
{
$constraint = new IsEqualIgnoringCase($expected);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are equal (with delta).
*
* @throws ExpectationFailedException
*/
final public static function assertEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void
{
$constraint = new IsEqualWithDelta(
$expected,
$delta,
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal.
*
* @throws ExpectationFailedException
*/
final public static function assertNotEquals(mixed $expected, mixed $actual, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqual($expected),
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal (canonicalizing).
*
* @throws ExpectationFailedException
*/
final public static function assertNotEqualsCanonicalizing(mixed $expected, mixed $actual, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqualCanonicalizing($expected),
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal (ignoring case).
*
* @throws ExpectationFailedException
*/
final public static function assertNotEqualsIgnoringCase(mixed $expected, mixed $actual, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqualIgnoringCase($expected),
);
static::assertThat($actual, $constraint, $message);
}
/**
* Asserts that two variables are not equal (with delta).
*
* @throws ExpectationFailedException
*/
final public static function assertNotEqualsWithDelta(mixed $expected, mixed $actual, float $delta, string $message = ''): void
{
$constraint = new LogicalNot(
new IsEqualWithDelta(
$expected,
$delta,
),
);
static::assertThat($actual, $constraint, $message);
}
/**
* @throws ExpectationFailedException
*/
final public static function assertObjectEquals(object $expected, object $actual, string $method = 'equals', string $message = ''): void
{
static::assertThat(
$actual,
static::objectEquals($expected, $method),
$message,
);
}
/**
* Asserts that a variable is empty.
*
* @throws ExpectationFailedException
* @throws GeneratorNotSupportedException
*
* @psalm-assert empty $actual
*/
final public static function assertEmpty(mixed $actual, string $message = ''): void
{
if ($actual instanceof Generator) {
throw GeneratorNotSupportedException::fromParameterName('$actual');
}
static::assertThat($actual, static::isEmpty(), $message);
}
/**
* Asserts that a variable is not empty.
*
* @throws ExpectationFailedException
* @throws GeneratorNotSupportedException
*
* @psalm-assert !empty $actual
*/
final public static function assertNotEmpty(mixed $actual, string $message = ''): void
{
if ($actual instanceof Generator) {
throw GeneratorNotSupportedException::fromParameterName('$actual');
}
static::assertThat($actual, static::logicalNot(static::isEmpty()), $message);
}
/**
* Asserts that a value is greater than another value.
*
* @throws ExpectationFailedException
*/
final public static function assertGreaterThan(mixed $expected, mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::greaterThan($expected), $message);
}
/**
* Asserts that a value is greater than or equal to another value.
*
* @throws ExpectationFailedException
*/
final public static function assertGreaterThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void
{
static::assertThat(
$actual,
static::greaterThanOrEqual($expected),
$message,
);
}
/**
* Asserts that a value is smaller than another value.
*
* @throws ExpectationFailedException
*/
final public static function assertLessThan(mixed $expected, mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::lessThan($expected), $message);
}
/**
* Asserts that a value is smaller than or equal to another value.
*
* @throws ExpectationFailedException
*/
final public static function assertLessThanOrEqual(mixed $expected, mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::lessThanOrEqual($expected), $message);
}
/**
* Asserts that the contents of one file is equal to the contents of another
* file.
*
* @throws ExpectationFailedException
*/
final public static function assertFileEquals(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new IsEqual(file_get_contents($expected));
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is equal to the contents of another
* file (canonicalizing).
*
* @throws ExpectationFailedException
*/
final public static function assertFileEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new IsEqualCanonicalizing(
file_get_contents($expected),
);
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is equal to the contents of another
* file (ignoring case).
*
* @throws ExpectationFailedException
*/
final public static function assertFileEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new IsEqualIgnoringCase(file_get_contents($expected));
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is not equal to the contents of
* another file.
*
* @throws ExpectationFailedException
*/
final public static function assertFileNotEquals(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new LogicalNot(
new IsEqual(file_get_contents($expected)),
);
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is not equal to the contents of another
* file (canonicalizing).
*
* @throws ExpectationFailedException
*/
final public static function assertFileNotEqualsCanonicalizing(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new LogicalNot(
new IsEqualCanonicalizing(file_get_contents($expected)),
);
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of one file is not equal to the contents of another
* file (ignoring case).
*
* @throws ExpectationFailedException
*/
final public static function assertFileNotEqualsIgnoringCase(string $expected, string $actual, string $message = ''): void
{
static::assertFileExists($expected, $message);
static::assertFileExists($actual, $message);
$constraint = new LogicalNot(
new IsEqualIgnoringCase(file_get_contents($expected)),
);
static::assertThat(file_get_contents($actual), $constraint, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file.
*
* @throws ExpectationFailedException
*/
final public static function assertStringEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new IsEqual(file_get_contents($expectedFile));
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file (canonicalizing).
*
* @throws ExpectationFailedException
*/
final public static function assertStringEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new IsEqualCanonicalizing(file_get_contents($expectedFile));
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is equal
* to the contents of a file (ignoring case).
*
* @throws ExpectationFailedException
*/
final public static function assertStringEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new IsEqualIgnoringCase(file_get_contents($expectedFile));
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is not equal
* to the contents of a file.
*
* @throws ExpectationFailedException
*/
final public static function assertStringNotEqualsFile(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new LogicalNot(
new IsEqual(file_get_contents($expectedFile)),
);
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is not equal
* to the contents of a file (canonicalizing).
*
* @throws ExpectationFailedException
*/
final public static function assertStringNotEqualsFileCanonicalizing(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new LogicalNot(
new IsEqualCanonicalizing(file_get_contents($expectedFile)),
);
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that the contents of a string is not equal
* to the contents of a file (ignoring case).
*
* @throws ExpectationFailedException
*/
final public static function assertStringNotEqualsFileIgnoringCase(string $expectedFile, string $actualString, string $message = ''): void
{
static::assertFileExists($expectedFile, $message);
$constraint = new LogicalNot(
new IsEqualIgnoringCase(file_get_contents($expectedFile)),
);
static::assertThat($actualString, $constraint, $message);
}
/**
* Asserts that a file/dir is readable.
*
* @throws ExpectationFailedException
*/
final public static function assertIsReadable(string $filename, string $message = ''): void
{
static::assertThat($filename, new IsReadable, $message);
}
/**
* Asserts that a file/dir exists and is not readable.
*
* @throws ExpectationFailedException
*/
final public static function assertIsNotReadable(string $filename, string $message = ''): void
{
static::assertThat($filename, new LogicalNot(new IsReadable), $message);
}
/**
* Asserts that a file/dir exists and is writable.
*
* @throws ExpectationFailedException
*/
final public static function assertIsWritable(string $filename, string $message = ''): void
{
static::assertThat($filename, new IsWritable, $message);
}
/**
* Asserts that a file/dir exists and is not writable.
*
* @throws ExpectationFailedException
*/
final public static function assertIsNotWritable(string $filename, string $message = ''): void
{
static::assertThat($filename, new LogicalNot(new IsWritable), $message);
}
/**
* Asserts that a directory exists.
*
* @throws ExpectationFailedException
*/
final public static function assertDirectoryExists(string $directory, string $message = ''): void
{
static::assertThat($directory, new DirectoryExists, $message);
}
/**
* Asserts that a directory does not exist.
*
* @throws ExpectationFailedException
*/
final public static function assertDirectoryDoesNotExist(string $directory, string $message = ''): void
{
static::assertThat($directory, new LogicalNot(new DirectoryExists), $message);
}
/**
* Asserts that a directory exists and is readable.
*
* @throws ExpectationFailedException
*/
final public static function assertDirectoryIsReadable(string $directory, string $message = ''): void
{
self::assertDirectoryExists($directory, $message);
self::assertIsReadable($directory, $message);
}
/**
* Asserts that a directory exists and is not readable.
*
* @throws ExpectationFailedException
*/
final public static function assertDirectoryIsNotReadable(string $directory, string $message = ''): void
{
self::assertDirectoryExists($directory, $message);
self::assertIsNotReadable($directory, $message);
}
/**
* Asserts that a directory exists and is writable.
*
* @throws ExpectationFailedException
*/
final public static function assertDirectoryIsWritable(string $directory, string $message = ''): void
{
self::assertDirectoryExists($directory, $message);
self::assertIsWritable($directory, $message);
}
/**
* Asserts that a directory exists and is not writable.
*
* @throws ExpectationFailedException
*/
final public static function assertDirectoryIsNotWritable(string $directory, string $message = ''): void
{
self::assertDirectoryExists($directory, $message);
self::assertIsNotWritable($directory, $message);
}
/**
* Asserts that a file exists.
*
* @throws ExpectationFailedException
*/
final public static function assertFileExists(string $filename, string $message = ''): void
{
static::assertThat($filename, new FileExists, $message);
}
/**
* Asserts that a file does not exist.
*
* @throws ExpectationFailedException
*/
final public static function assertFileDoesNotExist(string $filename, string $message = ''): void
{
static::assertThat($filename, new LogicalNot(new FileExists), $message);
}
/**
* Asserts that a file exists and is readable.
*
* @throws ExpectationFailedException
*/
final public static function assertFileIsReadable(string $file, string $message = ''): void
{
self::assertFileExists($file, $message);
self::assertIsReadable($file, $message);
}
/**
* Asserts that a file exists and is not readable.
*
* @throws ExpectationFailedException
*/
final public static function assertFileIsNotReadable(string $file, string $message = ''): void
{
self::assertFileExists($file, $message);
self::assertIsNotReadable($file, $message);
}
/**
* Asserts that a file exists and is writable.
*
* @throws ExpectationFailedException
*/
final public static function assertFileIsWritable(string $file, string $message = ''): void
{
self::assertFileExists($file, $message);
self::assertIsWritable($file, $message);
}
/**
* Asserts that a file exists and is not writable.
*
* @throws ExpectationFailedException
*/
final public static function assertFileIsNotWritable(string $file, string $message = ''): void
{
self::assertFileExists($file, $message);
self::assertIsNotWritable($file, $message);
}
/**
* Asserts that a condition is true.
*
* @throws ExpectationFailedException
*
* @psalm-assert true $condition
*/
final public static function assertTrue(mixed $condition, string $message = ''): void
{
static::assertThat($condition, static::isTrue(), $message);
}
/**
* Asserts that a condition is not true.
*
* @throws ExpectationFailedException
*
* @psalm-assert !true $condition
*/
final public static function assertNotTrue(mixed $condition, string $message = ''): void
{
static::assertThat($condition, static::logicalNot(static::isTrue()), $message);
}
/**
* Asserts that a condition is false.
*
* @throws ExpectationFailedException
*
* @psalm-assert false $condition
*/
final public static function assertFalse(mixed $condition, string $message = ''): void
{
static::assertThat($condition, static::isFalse(), $message);
}
/**
* Asserts that a condition is not false.
*
* @throws ExpectationFailedException
*
* @psalm-assert !false $condition
*/
final public static function assertNotFalse(mixed $condition, string $message = ''): void
{
static::assertThat($condition, static::logicalNot(static::isFalse()), $message);
}
/**
* Asserts that a variable is null.
*
* @throws ExpectationFailedException
*
* @psalm-assert null $actual
*/
final public static function assertNull(mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::isNull(), $message);
}
/**
* Asserts that a variable is not null.
*
* @throws ExpectationFailedException
*
* @psalm-assert !null $actual
*/
final public static function assertNotNull(mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::logicalNot(static::isNull()), $message);
}
/**
* Asserts that a variable is finite.
*
* @throws ExpectationFailedException
*/
final public static function assertFinite(mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::isFinite(), $message);
}
/**
* Asserts that a variable is infinite.
*
* @throws ExpectationFailedException
*/
final public static function assertInfinite(mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::isInfinite(), $message);
}
/**
* Asserts that a variable is nan.
*
* @throws ExpectationFailedException
*/
final public static function assertNan(mixed $actual, string $message = ''): void
{
static::assertThat($actual, static::isNan(), $message);
}
/**
* Asserts that an object has a specified property.
*
* @throws ExpectationFailedException
*/
final public static function assertObjectHasProperty(string $propertyName, object $object, string $message = ''): void
{
static::assertThat(
$object,
new ObjectHasProperty($propertyName),
$message,
);
}
/**
* Asserts that an object does not have a specified property.
*
* @throws ExpectationFailedException
*/
final public static function assertObjectNotHasProperty(string $propertyName, object $object, string $message = ''): void
{
static::assertThat(
$object,
new LogicalNot(
new ObjectHasProperty($propertyName),
),
$message,
);
}
/**
* Asserts that two variables have the same type and value.
* Used on objects, it asserts that two variables reference
* the same object.
*
* @psalm-template ExpectedType
*
* @psalm-param ExpectedType $expected
*
* @throws ExpectationFailedException
*
* @psalm-assert =ExpectedType $actual
*/
final public static function assertSame(mixed $expected, mixed $actual, string $message = ''): void
{
static::assertThat(
$actual,
new IsIdentical($expected),
$message,
);
}
/**
* Asserts that two variables do not have the same type and value.
* Used on objects, it asserts that two variables do not reference
* the same object.
*
* @throws ExpectationFailedException
*/
final public static function assertNotSame(mixed $expected, mixed $actual, string $message = ''): void
{
if (is_bool($expected) && is_bool($actual)) {
static::assertNotEquals($expected, $actual, $message);
}
static::assertThat(
$actual,
new LogicalNot(
new IsIdentical($expected),
),
$message,
);
}
/**
* Asserts that a variable is of a given type.
*
* @psalm-template ExpectedType of object
*
* @psalm-param class-string