如何使用 phpunit 模拟 PHP 中的 SimpleXMLElement?

How to mock the SimpleXMLElement in PHP using phpunit?

我有以下功能:

function get_svg_dimensions($svg)
    {
        $svg = simplexml_load_file($svg);
        $width = 0;
        $height = 0;

        if ($svg) {
            $attributes = $svg->attributes();

            if (isset($attributes->width, $attributes->height)) {
                $width = intval($attributes->width);
                $height = intval($attributes->height);
            } elseif (isset($attributes->viewBox)) {
                $sizes = explode(' ', $attributes->viewBox);

                if (isset($sizes[2], $sizes[3])) {
                    $width = intval($sizes[2]);
                    $height = intval($sizes[3]);
                }
            }
        }

        return ['width' => $width, 'height' => $height];
    }

我正在尝试模拟 $attributes = $svg->attributes();

这是测试:

public function testGetSvgDimension()
    {
        $mockAttributes = [
            'width' => '100px',
            'height' => '100px',
            'viewBox' => '0 0 100 100',
        ];

        $mockSimpleXmlElement = (object)[
            '@attributes' => $mockAttributes
        ];

        $expected_value = [
            'width' => '100px',
            'height' => '100px',
        ];

        Functions\when('simplexml_load_file')->justReturn($mockSimpleXmlElement);
        $request = $this->createMock(SimpleXMLElement::class);
        $request->expects($this->once())->method('attributes')->willReturn($mockAttributes);

        static::assertEquals($expected_value, sg_core_t_get_svg_dimensions('mock_path'));
    } 

我在这一行收到以下错误
$request = $this->createMock(SimpleXMLElement::class);:

Mock_SimpleXMLElement_eba23fd5::__phpunit_setReturnValueGeneration(): Node no longer exists

我曾尝试在 $request = $this->createMock(Traversable::class); 中使用 Traversable::class 而不是 SimpleXMLElement::class,但在这种情况下,我收到以下警告:

Trying to configure method "attributes" which cannot be configured because it does not exist, has not been specified, is final, or is static

这会将此函数的测试覆盖率百分比变为 0。

PHPUnit 版本为 7.5.20。我无法升级到 8 或 9,因为该网站是使用 WordPress 构建的,WordPress 目前仅与 PHPUnit 兼容 7.x
PHP 版本为 7.2.26

有人可以帮忙吗?

找到解决方案。

基本上,我做错的是我在这里返回了一个错误的值: Functions\when('simplexml_load_file')->justReturn($mockSimpleXmlElement); 然后尝试模拟 SimpleXMLElement class.

我应该做的是我应该在模拟 simplexml_load_file 时返回一个 SimpleXMLElement 并向其添加属性。

查看完整代码:

public function dataProvider_GetSvgDimensions()
    {
        return [
            'height and width attributes exist on the svg' => [
                (object)[
                    'width' => '100',
                    'height' => '100',
                ]
            ],
            'height and width attributes do not exist on the svg - viewBox exists' => [
                (object)[
                    'viewBox' => '0 0 100 100',
                ]
            ],
        ];
    }

    /**
     * @dataProvider dataProvider_GetSvgDimensions
     *
     * @param $mockAttributes
     */
    public function testGetSvgDimension($mockAttributes)
    {
        $expected_value = [
            'width' => '100',
            'height' => '100',
        ];

        $mockSimpleXmlElement = new SimpleXMLElement('<root />');
        foreach ($mockAttributes as $attr => $value) {
            $mockSimpleXmlElement->addAttribute($attr, $value);
        }

        Functions\when('simplexml_load_file')->justReturn($mockSimpleXmlElement);

        static::assertEquals($expected_value, sg_core_t_get_svg_dimensions('mock_path'));
    }