【问题标题】:How to test constructor that sets protected properties?如何测试设置受保护属性的构造函数?
【发布时间】:2012-01-28 16:55:28
【问题描述】:

嗯,我是单元测试新手(使用 phpUnit),刚刚开始测试我的一类。

实际的构造函数如下所示:

/**
 * Loads configuration.
 */
function __construct() {

    $config =
        Kohana::$config->load('koffee');

    $this->_table_name = $config->table_name;
    $this->_table_columns = $config->table_columns;

}

它基本上从另一个文件中获取配置并将其设置为该对象的受保护属性。

这是单元测试的样子(它还没有完成,这就是我需要帮助的地方):

/**
 * Tests that config is loaded and correct.
 */
function testConfigIsLoadedAndCorrect() {

    $object = new Model_Article();

    $config = Kohana::$config->load('koffee');

    // Compare object's **protected** properties to local `$config`. How?!

}

问题是属性受到保护,我不能那么容易地访问它们......

我目前看到的可能解决方案:

  1. 更改属性的可见性(我不喜欢这样),
  2. 在我测试的类中添加所谓的“getter”——不是单元测试(我也不喜欢这个);

您可能觉得这很有趣,但是,正如我所说,我是单元测试的新手。非常感谢任何帮助。

【问题讨论】:

  • 你还没有写出你真正想要测试的什么以及你认为有问题的为什么
  • 我想将对象的 protected 属性与测试中所写的本地 $config 进行比较。

标签: php unit-testing kohana phpunit visibility


【解决方案1】:

我过去使用的一种技术是创建一个 Tester 类,该类公开适当的方法来测试对象。在这种情况下,Model_Article_Tester 将继承 Model_Article 并公开 get 方法。这样做的好处是您可以在不影响生产代码的情况下公开测试所需的内容。

【讨论】:

  • 谢谢。这似乎是一种方法。
【解决方案2】:

您可以创建一个子类来公开您需要的数据并仅将其用于单元测试。

您还可以测试类的行为而不是数据。 Model_Article 必须对 table_name 和 table_columns 做一些事情,以便测试该行为。例如,如果 Model_Article 用于创建 html 表,那么您可以设置配置值,创建 Model_Article,使用它来创建 html,然后断言它匹配硬编码字符串,如<table title='name'><tr><th>col1</th><th>col2</th</tr></table>

[编辑] 你也可以依靠构造函数注入来传递 table_name 和 table_columns,而不是对配置有隐藏的依赖。

【讨论】:

  • 能给我一个构造函数注入的例子吗?
  • 构造函数中需要的所有参数都是构造函数的参数:function __construct($table_name, $table_columns)。然后,创建者服务可以使用注入的配置来实例化所需的类,而无需类知道配置是如何完成的,并且创建者知道哪些选项可用于配置。
  • 这意味着我需要从类中单独加载该配置,然后将其传递给构造函数(new Model_Article('x', 'y'))?
  • 在现实世界的代码中是的,这可能就是你要做的。但是在单元测试中,您可以传递自己的值并确保您只测试 Model_Article 是否按预期工作,而不必担心配置。这也使 Model_Article 更具可预测性,因为您知道它仅依赖于其输入而不是隐藏值。
【解决方案3】:

单元测试是关于单元测试。受保护的成员不是 unit 的公共接口的一部分,这是您在编写单元测试时需要关心的全部。

您不会测试一个单元的内部结构,但它会按预期工作。

如果您无论如何都想做这样的事情,您可以使用Serialization­Docscasting to arrayReflection­Docs 来检查对象的受保护/私有属性或执行对象的受保护/私有方法。


另请参阅: PhpUnit private method testingSO Q&A

【讨论】:

【解决方案4】:

你可以尝试使用ReflectionClass::newInstanceWithoutConstructor

$reflector = new ReflectionClass('Model_Article');
$object = $reflector->newInstanceWithoutConstructor();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2015-08-12
    • 2016-04-07
    • 2011-05-30
    • 1970-01-01
    相关资源
    最近更新 更多