关于单元测试:如何在PHP中访问私有属性?

How do I access private attributes in PHP?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Best practices to test protected methods with PHPUnit

1
2
3
4
5
6
7
8
9
10
11
12
class Footer
{
  private $_isEnabled;

  public function __construct(){
    $this->_isEnabled = true;
  }

  public function disable(){
    $this->_isEnabled = false;
  }  
}

在我将_isEanabled设置为false后,我正在为禁用功能编写单元测试时,我想断言它是否为假。

但是如何访问$_isEnabled

这是我的测试功能:

1
2
3
4
5
public function testDisable(){
  $footer = new Footer();
  $footer->disable();
  $this->assertFalse($footer->_isEnable);
}

简短回答:

你不能。那是私有的意思......

答案很长:

你可以使用反射来做到这一点:

http://php.net/manual/en/book.reflection.php

但它有点复杂,并且增加了另一层容易出现故障,因此它不是测试的最佳方式......

我更喜欢创建一个getter函数:

1
2
3
public function getEnabled() {
   return $this->_isEnabled;
}

但如果你没有这么简单,我认为你不想创造它......但考虑到替代方案,你可能会重新考虑它。


我怀疑这个得分:这个班不是"代数"完整的。缺少public function isEnabled()。如果单元测试没有关于状态的信息,那么其他类客户端也将错过此信息。

对私有内容进行单元测试无助于对公共API进行任何说明,但检查内部操作应该是显而易见的。

一般来说,依靠实施进行单元测试是不好的事情;然后重新实现也可以维护单元测试。


一个无障碍的财产必须是公开的,我认为这是自我解释。但是,您可能会遇到代码,其中受保护和私有属性似乎可以通过类似于访问公共变量的方式访问。

这是使用魔术getter方法完成的:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Footer
{
    private $_isEnabled;

    public function __get($propName)
    {
        if (!isset($this->{$propName}))
        {
            throw new Exception($propName.' is not set');
        }
        return $this->{$propName};
    }
}

每次尝试访问不存在或不存在的属性时,都会调用此魔术方法。简而言之:

1
$instance->_isEnabled;//will work.

您可以根据需要更改此方法,例如,不再需要下划线...您可以使用此方法做很多事情。
请参阅手册页