使用带有 PHPUnit 模拟对象的 get_class 测试代码

2022-01-25 00:00:00 php phpunit

Using PHPUnit and a mock object, I am trying to test some code that uses get_class to determine if an object is included by a filter or not.

Here is the class to be tested:

class BlockFilter implements FilterInterface
{
    private $classes;

    public function __construct(array $classes = array())
    {
        $this->classes = $classes;
    }

    public function isIncluded(NodeTraversableInterface $node)
    {
        if (Type::BLOCK != $node->getDocumentType()) {
            return false;
        }

        if (! empty($this->classes)) {
            /*** HERE IS THE PROBLEM: ***/
            return in_array(get_class($node), $this->classes);
        }

        return true;
    }
}

Here is the method from my unit test:

public function testIfContainerBlockIsIncluded()
{
    $containerBlock = $this->getMock('PwnContentBundleDocumentContainerBlock');
    $containerBlock->expects($this->any())->method('getDocumentType')->will($this->returnValue(Type::BLOCK));

    $filter = new BlockFilter(array('PwnContentBundleDocumentContainerBlock'));
    $this->assertTrue($filter->isIncluded($containerBlock));
}

The mock object $containerBlock behaves like the real object PwnContentBundleDocumentContainerBlock; even code using instanceof works (because PHPUnit makes it a subclass of the real class, I believe).

The code being tested uses get_class to get a string value of the class and compare it with an array of expected class names. Unfortunately, for the mock object, get_class returns something like this:

Mock_ContainerBlock_ac231064

(the _ac231064 suffix changes on each invocation).

This causes my test to fail, so what are my options?

  • Rework the code to avoid using get_class? This implies get_class should not be used when trying to write testable code.
  • Use a real instance of the ContainerBlock class instead of a mock? This means we are effectively testing both classes at once.
  • Some other awesomely clever trick that you're all going to suggest??? ;)

Thanks for any help...

解决方案

Pass the Mock's class name in the test:

new BlockFilter(array(get_class($this->containerBlock)));

相关文章