Skip to content

Commit

Permalink
Merge pull request #116 from Yoast/feature/phpunit-10.1-add-assertobj…
Browse files Browse the repository at this point in the history
…ecthaspropertytrait

PHPUnit 10.1 | AssertObjectProperty trait: polyfill the Assert::assertObject[Not]HasProperty() methods
  • Loading branch information
jrfnl authored Apr 16, 2023
2 parents cc836eb + 2f3e4e3 commit 520d770
Show file tree
Hide file tree
Showing 10 changed files with 622 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,18 @@ This method was introduced in PHPUnit 10.0.0.

[`Assert::assertIsList()`]: https://docs.phpunit.de/en/main/assertions.html#assertislist

#### PHPUnit < 10.1.0: `Yoast\PHPUnitPolyfills\Polyfills\AssertIsList`

Polyfills the following method:
| | |
|---------------------------------------|------------------------------------------|
| [`Assert::assertObjectHasProperty()`] | [`Assert::assertObjectNotHasProperty()`] |

These methods were introduced in PHPUnit 10.1.0 as alternatives to the `Assert::assertObjectHasAttribute()` and `Assert::assertObjectNotHasAttribute()` methods, which were hard deprecated (warning) in PHPUnit 9.6.1 and removed in PHPUnit 10.0.0.

[`Assert::assertObjectHasProperty()`]: https://docs.phpunit.de/en/main/assertions.html#assertObjectHasProperty
[`Assert::assertObjectNotHasProperty()`]: https://docs.phpunit.de/en/main/assertions.html#assertObjectHasProperty


### Helper traits

Expand Down
21 changes: 21 additions & 0 deletions phpunitpolyfills-autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public static function load( $className ) {
self::loadAssertIgnoringLineEndings();
return true;

case 'Yoast\PHPUnitPolyfills\Polyfills\AssertObjectProperty':
self::loadAssertObjectProperty();
return true;

case 'Yoast\PHPUnitPolyfills\TestCases\TestCase':
self::loadTestCase();
return true;
Expand Down Expand Up @@ -331,6 +335,23 @@ public static function loadAssertIgnoringLineEndings() {
require_once __DIR__ . '/src/Polyfills/AssertIgnoringLineEndings_Empty.php';
}

/**
* Load the AssertObjectProperty polyfill or an empty trait with the same name
* if a PHPUnit version is used which already contains this functionality.
*
* @return void
*/
public static function loadAssertObjectProperty() {
if ( \method_exists( Assert::class, 'assertObjectHasProperty' ) === false ) {
// PHPUnit < 10.1.0.
require_once __DIR__ . '/src/Polyfills/AssertObjectProperty.php';
return;
}

// PHPUnit >= 10.1.0.
require_once __DIR__ . '/src/Polyfills/AssertObjectProperty_Empty.php';
}

/**
* Load the appropriate TestCase class based on the PHPUnit version being used.
*
Expand Down
154 changes: 154 additions & 0 deletions src/Polyfills/AssertObjectProperty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<?php

namespace Yoast\PHPUnitPolyfills\Polyfills;

use PHPUnit\Framework\Assert;
use ReflectionObject;
use TypeError;
use Yoast\PHPUnitPolyfills\Autoload;

/**
* Polyfill the Assert::assertObjectHasProperty() and Assert::assertObjectNotHasProperty() methods,
* which replace the Assert::assertObjectHasAttribute() and Assert::assertObjectNotHasAttribute() methods.
*
* Introduced in PHPUnit 10.1.0.
*
* The Assert::assertObjectHasAttribute() and Assert::assertObjectNotHasAttribute() methods
* were deprecated in PHPUnit 9.6.1 and removed in PHPUnit 10.0.0.
*
* @link https://github.com/sebastianbergmann/phpunit/pull/5231
*
* @since 2.1.0
*/
trait AssertObjectProperty {

/**
* Asserts that an object has a specified property.
*
* @param string $propertyName The name of the property.
* @param object $object The object on which to check whether the property exists.
* @param string $message Optional failure message to display.
*
* @return void
*
* @throws TypeError When any of the passed arguments do not meet the required type.
*/
final public static function assertObjectHasProperty( $propertyName, $object, $message = '' ) {
/*
* Parameter input validation.
* In PHPUnit this is done via PHP native type declarations. Emulating this for the polyfill,
* including for those PHPUnit versions where we hand to a native PHPUnit alternative, as
* otherwise the method referenced in the error message would get very confusing and inconsistent.
*/
if ( \is_string( $propertyName ) === false ) {
throw new TypeError(
\sprintf(
'Argument 1 passed to assertObjectHasProperty() must be of type string, %s given',
\gettype( $propertyName )
)
);
}
if ( \is_object( $object ) === false ) {
throw new TypeError(
\sprintf(
'Argument 2 passed to assertObjectHasProperty() must be of type object, %s given',
\gettype( $object )
)
);
}

if ( \method_exists( Assert::class, 'assertObjectHasAttribute' )
&& \version_compare( Autoload::getPHPUnitVersion(), '9.6.0', '<=' )
) {
// PHPUnit <= 9.6.0.
static::assertObjectHasAttribute( $propertyName, $object, $message );
return;
}

/*
* PHPUnit 9.6.1+ and PHPUnit 10.0.x.
* Note: letting this polyfill code kick in for PHPUnit 9.6.1+ as well
* to prevent the PHPUnit deprecation notice showing.
*/
$msg = self::assertObjectHasPropertyFailureDescription( $object );
$msg .= \sprintf( ' has property "%s".', $propertyName );
if ( $message !== '' ) {
$msg = $message . \PHP_EOL . $msg;
}

$hasProperty = ( new ReflectionObject( $object ) )->hasProperty( $propertyName );
static::assertTrue( $hasProperty, $msg );
}

/**
* Asserts that an object does not have a specified property.
*
* @param string $propertyName The name of the property.
* @param object $object The object on which to check whether the property exists.
* @param string $message Optional failure message to display.
*
* @return void
*
* @throws TypeError When any of the passed arguments do not meet the required type.
*/
final public static function assertObjectNotHasProperty( $propertyName, $object, $message = '' ) {
/*
* Parameter input validation.
* In PHPUnit this is done via PHP native type declarations. Emulating this for the polyfill,
* including for those PHPUnit versions where we hand to a native PHPUnit alternative, as
* otherwise the method referenced in the error message would get very confusing and inconsistent.
*/
if ( \is_string( $propertyName ) === false ) {
throw new TypeError(
\sprintf(
'Argument 1 passed to assertObjectNotHasProperty() must be of type string, %s given',
\gettype( $propertyName )
)
);
}
if ( \is_object( $object ) === false ) {
throw new TypeError(
\sprintf(
'Argument 2 passed to assertObjectNotHasProperty() must be of type object, %s given',
\gettype( $object )
)
);
}

if ( \method_exists( Assert::class, 'assertObjectNotHasAttribute' )
&& \version_compare( Autoload::getPHPUnitVersion(), '9.6.0', '<=' )
) {
// PHPUnit <= 9.6.0.
static::assertObjectNotHasAttribute( $propertyName, $object, $message );
return;
}

/*
* PHPUnit 9.6.1+ and PHPUnit 10.0.x.
* Note: letting this polyfill code kick in for PHPUnit 9.6.1+ as well
* to prevent the PHPUnit deprecation notice showing.
*/
$msg = self::assertObjectHasPropertyFailureDescription( $object );
$msg .= \sprintf( ' does not have property "%s".', $propertyName );
if ( $message !== '' ) {
$msg = $message . \PHP_EOL . $msg;
}

$hasProperty = ( new ReflectionObject( $object ) )->hasProperty( $propertyName );
static::assertFalse( $hasProperty, $msg );
}

/**
* Returns the description of the failure.
*
* @param object $object The object under test.
*
* @return string
*/
private static function assertObjectHasPropertyFailureDescription( $object ) {
return \sprintf(
'Failed asserting that object of class "%s"',
\get_class( $object )
);
}
}
10 changes: 10 additions & 0 deletions src/Polyfills/AssertObjectProperty_Empty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Yoast\PHPUnitPolyfills\Polyfills;

/**
* Empty trait for use with PHPUnit >= 10.1.0 in which this polyfill is not needed.
*
* @since 2.1.0
*/
trait AssertObjectProperty {}
2 changes: 2 additions & 0 deletions src/TestCases/TestCasePHPUnitGte8.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Yoast\PHPUnitPolyfills\Polyfills\AssertionRenames;
use Yoast\PHPUnitPolyfills\Polyfills\AssertIsList;
use Yoast\PHPUnitPolyfills\Polyfills\AssertObjectEquals;
use Yoast\PHPUnitPolyfills\Polyfills\AssertObjectProperty;
use Yoast\PHPUnitPolyfills\Polyfills\EqualToSpecializations;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectExceptionMessageMatches;

Expand All @@ -31,6 +32,7 @@ abstract class TestCase extends PHPUnit_TestCase {
use AssertionRenames;
use AssertIsList;
use AssertObjectEquals;
use AssertObjectProperty;
use EqualToSpecializations;
use ExpectExceptionMessageMatches;

Expand Down
2 changes: 2 additions & 0 deletions src/TestCases/TestCasePHPUnitLte7.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yoast\PHPUnitPolyfills\Polyfills\AssertIsList;
use Yoast\PHPUnitPolyfills\Polyfills\AssertIsType;
use Yoast\PHPUnitPolyfills\Polyfills\AssertObjectEquals;
use Yoast\PHPUnitPolyfills\Polyfills\AssertObjectProperty;
use Yoast\PHPUnitPolyfills\Polyfills\AssertStringContains;
use Yoast\PHPUnitPolyfills\Polyfills\EqualToSpecializations;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectExceptionMessageMatches;
Expand All @@ -37,6 +38,7 @@ abstract class TestCase extends PHPUnit_TestCase {
use AssertIsList;
use AssertIsType;
use AssertObjectEquals;
use AssertObjectProperty;
use AssertStringContains;
use EqualToSpecializations;
use ExpectExceptionMessageMatches;
Expand Down
2 changes: 2 additions & 0 deletions src/TestCases/XTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yoast\PHPUnitPolyfills\Polyfills\AssertIsList;
use Yoast\PHPUnitPolyfills\Polyfills\AssertIsType;
use Yoast\PHPUnitPolyfills\Polyfills\AssertObjectEquals;
use Yoast\PHPUnitPolyfills\Polyfills\AssertObjectProperty;
use Yoast\PHPUnitPolyfills\Polyfills\AssertStringContains;
use Yoast\PHPUnitPolyfills\Polyfills\EqualToSpecializations;
use Yoast\PHPUnitPolyfills\Polyfills\ExpectExceptionMessageMatches;
Expand Down Expand Up @@ -39,6 +40,7 @@ abstract class XTestCase extends PHPUnit_TestCase {
use AssertIsList;
use AssertIsType;
use AssertObjectEquals;
use AssertObjectProperty;
use AssertStringContains;
use EqualToSpecializations;
use ExpectExceptionMessageMatches;
Expand Down
Loading

0 comments on commit 520d770

Please sign in to comment.