0

我似乎在测试设置了私有实例变量时遇到了一些麻烦。我的想法是删除类并将实例变量公开,以便我可以测试 setter 方法。这看起来很简单,但我似乎无法让它正常工作。或者也许有一些更好的方法来测试设置私有变量。

班级

<?php
namespace PureChat\src\messages;

/**
 * Message class for containing information about a message.
 */
class Message
{
    /**
     * Contains the message text.
     * @var string
     */
    private $messageText;

    /**
     * Sets the instance variable $messageText.
     * @param string $text The text to assign.
     */
    public function setText($text)
    {
        $this->messageText = $text;
    }
}

PHP单元测试

<?php
use PureChat\src\messages\Message;

class MessageTest extends \PHPUnit_Framework_TestCase
{
    public function testMessageCanSetText()
    {
        $message = new MessageStub;
        $message->setText('test-text');
        $this->assertEquals(
            $message->messageText, 'test-text');
    }
}

class MessageStub extends Message
{
    public $messageText;
}

运行时,测试失败"Failed asserting that 'test-text' matches expected null."我的第一个想法是存根类可能没有继承该setText方法,所以我也使用 进行了测试method_exists,但是该方法确实存在,所以我很茫然。

4

2 回答 2

1

私有属性不是继承的,所以$messageText已经不在MessageStub类内部。并且不能通过继承的方法设置setText

然后你assertEquals()以错误的顺序使用参数:第一个应该是你期望的值,第二个是你测试的值。翻转参数-然后错误消息更有意义,因为当前消息说您期望NULL-但您期望字符串'test-text'。

然后我们来到测试哲学的话题。一个好的单元测试只检查对象的外部,而不应该关心内部工作。如果您设置了一个值,那么设置它的成功应该可以从外部以某种方式检测到。当您只有非常基本的 setter/getter 组合时,测试它们确实很无聊,但这就是您应该做的:设置一个有效值,取回它,断言它与以前相同,并断言没有错误发生(这是由 PHPUnit 自动完成的,因为任何 PHP 错误或异常都会导致测试失败)。

如果该值没有 getter - 无论如何设置该值都没有用,因为它从未使用过,或者您可以通过测试使用该值的部分来测试它。

$message->setText('foo');
$message->saveText(); // uses value from setText()

如果您想对此进行测试,您可能会在一次测试中调用这两种方法。并且您需要测试saveText单独调用是否会触发错误。或保存默认值。

或者你得出的结论是,有两个方法来做一件事并不是一个好主意,因为测试它们并不容易,所以你的测试经验可能会让你考虑改进那个消息对象的 API。您可能想以某种方式摆脱这种setText方法。

是的,使用反射来访问私有属性是一种测试它的方法。但是现在您将测试与对象的内部构造紧密绑定。如果您重命名私有属性,您的测试会中断 - 但它不应该中断,因为您没有更改公共接口。

于 2013-11-01T11:29:33.067 回答
0

你可以使用反射

$message = new Message;
$message->setText('test-text');

$property = (new \ReflectionObject($message))->getProperty('messageText');
$property->setAccessible(true);
$value = $property->getValue($message);
$property->setAccessible(false); // restore state

echo $value;
于 2013-11-01T01:14:27.730 回答