写 Laravel 测试代码 (四)

在写单元测试时,有时候需要测试A class 的 protected or private method,可以使用 Class Reflection 来做,而不是去改成public,破坏封装

laravel 的 abstract TestCase class 中添加一个方法就行:

    /**
     * Call protected or private method of a class.
     *
     * @param object $object      instantiated object that we will run method on.
     * @param string $method_name method name to call
     * @param array  $parameters  array of parameters to pass into method.
     *
     * @return mixed Method return.
     */
    protected function invokeNonPublicMethod($object, string $method_name, ...$parameters)
    {
        $reflection = new ReflectionClass(get_class($object));
        $method     = $reflection->getMethod($method_name);
        $method->setAccessible(true);

        return $method->invokeArgs($object, $parameters);
    }

然后在 test case 中这样写测试就行:

final AccountTest extends TestCase
{
    public function testValue()
    {
        $account = new Account()

        // actual
        $values = $this->invokeNonPublicMethod($account, 'privateMethod', [1, 2, 3]);
        // $values = $this->invokeNonPublicMethod($account, 'protectedMethod', [2, 3, 4]);

        // assert
        ...
    }

}
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 1

这样传引用参数会报错,被转换成值参数了,我改成下面这样

    protected function getNonPublicMethod($object, string $method_name)
    {
        $reflection = new \ReflectionClass(get_class($object));
        $method     = $reflection->getMethod($method_name);
        $method->setAccessible(true);

        return $method;
    }

    protected function invokeNonPublicMethod($object, string $method_name, ...$parameters)
    {
        return $this->getNonPublicMethod($object, $method_name)->invokeArgs($object, $parameters);
    }

需要传引用参数的时候就调上面的函数,然后手动调用invokeArgs

7年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!