sick_o
sick_o

Reputation: 36

PHPUnit - Check if an array contains an object of a specific type

While unit testing in PHPUnit, I'm in a situation where I need to check if an array contains al least one object of a specific type.

Here's a trivial example of what I'm looking for

$obj_1 = new Type1;
$obj_2 = new Type2; 

$container = array( $obj_1, $obj_2 );

// some logic and array manipulation here

// need something like this
$this->assertArrayHasObjectOfClass( 'Type1', $container );

Obviously I can do that with custom code, but is there any assertion (or combination of them) which allows me to do that?

I need to do that many times in multiple tests so, if the assertion I need doesn't esist, how do I extend the set of PHPUnit assertions?

EDIT: custom solution with trait

As suggested by Vail, I came up with a custom solution for this using traits. Here's a semplified version.

// trait code
trait CustomAssertTrait
{
    public function assertArrayHasObjectOfType( $type, $array, $message = '' ) {

        $found = false;

        foreach( $array as $obj ) {
            if( get_class( $obj ) === $type ) {
                $found = true;
                break;
            }
        }

        $this->assertTrue( $found, $message );

    }
}

// test code
class CustomTest extends PHPUnit_Framework_TestCase {
   use CustomAssertTrait;

   // test methods... 
}

Upvotes: 2

Views: 8440

Answers (4)

Volmarg Reiso
Volmarg Reiso

Reputation: 483

Answering since I was looking for an info too and found that while digging in methods list:

  • phpunit-version: 9.5.13
  • method name: assertContainsOnly
  • example: $this->assertContainsOnly(Dto::class, $this->provider->provide());

Upvotes: 1

AbraCadaver
AbraCadaver

Reputation: 79014

Similar to your solution:

$found = (bool)array_filter($array, function($v) use ($type) {
                                        return get_class($v) === $type;
                                    });

Upvotes: 0

user4494077
user4494077

Reputation:

If you check only one object use method assertContains() and place array or Traversable as second parameter. But here object must have same properties as one you are looking for (eg. id, title, etc.) ex.

$obj_x = new Type1;
$this->assertContains($obj_x, $container);

If all objects in array or Traversable have same ancestor or interface, you can use method assertContainsOnlyInstancesOf() ex.

$this->assertContainsOnlyInstancesOf(Type1Type2Interface::class, $container);

https://phpunit.de/manual/5.7/en/appendixes.assertions.html#appendixes.assertions.assertContainsOnlyInstancesOf

Upvotes: 6

Vail
Vail

Reputation: 608

I don`t think that there is an assertion for this. You will need to write some custom code.

About extendig PHPUnit assertions you could create trait with your own assertion method and add it to specific tests.

Or look at this https://phpunit.de/manual/current/en/extending-phpunit.html

Upvotes: 0

Related Questions