【问题标题】:phpunit abstract class constantphpunit 抽象类常量
【发布时间】:2011-10-20 11:53:10
【问题描述】:

我正在尝试找到一种方法来测试必须存在并且匹配/不匹配值的抽象类常量。示例:

// to be extended by ExternalSDKClild
abstract class ExternalSDK {
    const VERSION = '3.1.1.'; 
}


class foo extends AController {
    public function init() {   
        if ( ExternalSDK::VERSION !== '3.1.1' ) {
            throw new Exception('Wrong ExternalSDK version!');
        }

        $this->setExternalSDKChild(new ExternalSDKChild());
    }
}

限制... 我们使用的框架不允许在 init() 方法中进行依赖注入。 (重构 init() 方法的建议可能是要走的路……)

我运行的单元测试和代码覆盖率,涵盖了除异常之外的所有内容。我想不出办法让 ExternalSDK::Version 与原来的不同。

欢迎所有想法

【问题讨论】:

    标签: class phpunit constants abstract


    【解决方案1】:

    首先,将对new 的调用重构为一个单独的方法。

    其次,添加一个获取版本的方法,而不是直接访问常量。 PHP 中的类常量在解析时会编译到文件中,并且无法更改。* 由于它们是静态访问的,因此如果不交换具有相同名称的不同类声明,就无法覆盖它。使用标准 PHP 做到这一点的唯一方法是在一个单独的进程中运行测试,这非常昂贵。

    class ExternalSDK {
        const VERSION = '3.1.1';
    
        public function getVersion() {
            return static::VERSION;
        }
    }
    
    class foo extends AController {
        public function init() {
            $sdk = $this->createSDK();
            if ( $sdk->getVersion() !== '3.1.1' ) {
                throw new Exception('Wrong ExternalSDK version!');
            }
    
            $this->setExternalSDKChild($sdk);
        }
    
        public function createSDK() {
            return new ExternalSDKChild();
        }
    }
    

    现在进行单元测试。

    class NewerSDK extends ExternalSDK {
        const VERSION = '3.1.2';
    }
    
    /**
     * @expectedException Exception
     */
    function testInitFailsWhenVersionIsDifferent() {
        $sdk = new NewerSDK();
        $foo = $this->getMock('foo', array('createSDK'));
        $foo->expects($this->once())
            ->method('createSDK')
            ->will($this->returnValue($sdk));
        $foo->init();
    }
    

    *Runkit 提供runkit_constant_redefine() 可能在这里工作。您需要手动捕获异常而不是使用@expectedException,这样您就可以将常量重置回正确的值。或者您可以在tearDown() 中进行。

    function testInitFailsWhenVersionIsDifferent() {
        try {
            runkit_constant_redefine('ExternalSDK::VERSION', '3.1.0');
            $foo = new foo();
            $foo->init();
            $failed = true;
        }
        catch (Exception $e) {
            $failed = false;
        }
        runkit_constant_redefine('ExternalSDK::VERSION', '3.1.1');
        if ($failed) {
            self::fail('Failed to detect incorrect SDK version.');
        }
    }
    

    【讨论】:

    • 拥有一个类常量的 getter 完全破坏了常量恕我直言的目的
    • @donatJ - 您可以通过删除常量并直接从 getVersion 返回值来轻松地重构它,但是通过较小的更改来演示这种单元测试技术更容易。
    猜你喜欢
    • 2015-07-14
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 2012-12-04
    • 2012-05-09
    • 2021-07-18
    • 1970-01-01
    相关资源
    最近更新 更多