PHPUnit,测试多个值

时间:2012-03-02 09:54:22

标签: php phpunit assertions

如何为同一属性测试多个值?

class Test {

    private $_optionalValue = null;

    function setValue(String $optionalValue)
    {
        $this->_optionalValue = $optionalValue;
    }
}

所以在这里,“$ _optionalValue”可能是NULL或用户定义的值,但是当我用phpunit检查时这样:

$optionalValue = PHPUnit_Util_Class::getObjectAttribute($my_object, '_optionalValue');

$this->assertThat(
    $optionalValue,
    $this->logicalXor(
        $this->assertNull($optionalValue),
        $this->logicalAnd(
            $this->assertAttributeInternalType('string', '_optionalValue', $optionalValue),
            $this->assertRegExp('/[0-9]{2}:[0-9]{2}:[0-9]{2}/', (string) $optionalValue)
        )
    )
);

Regexp断言失败,因为$ optionalValue不是String(默认情况下为null)

2 个答案:

答案 0 :(得分:2)

您正在调用assertThat内部进行断言,但您需要构建并传入约束。所有以assert开头的方法都会立即评估该值,并在不匹配时抛出异常。每个断言都有一个相应的约束类,有些具有工厂方法。

$optionalValue = PHPUnit_Util_Class::getObjectAttribute($my_object, '_optionalValue');

$this->assertThat(
    $optionalValue,
    $this->logicalXor(
        $this->isNull(),
        $this->logicalAnd(
            new PHPUnit_Framework_Constraint_IsType('string'),
            new PHPUnit_Framework_Constraint_PCREMatch('/[0-9]{2}:[0-9]{2}:[0-9]{2}/')
        )
    )
);
顺便说一句,我同意a)你最好不要像这样测试内部状态,b)你应该设计你的测试,以便你知道期望的值。每个测试都应该将系统置于单个预期状态。即使使用随机数的代码也应该使用存根替换固定序列。任何允许多种可能性的测试都是可疑的。

答案 1 :(得分:1)

你正在测试一个通常应该避免的对象的私有属性,因为它是单元的内部,你不应该关心它。

如果您的单位需要验证该类的值,则通常可能会验证某种类型的值。

因此,您可以将验证的逻辑封装到它自己的单元中,例如验证者:

class FooValueValidator implements Validator {
    /**
     * @var string
     */
    private $value;

    /**
     * @var string
     */
    private $regex = '/[0-9]{2}:[0-9]{2}:[0-9]{2}/';

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

    /**
     * @return bool
     */
    public function isValid() {

        if (is_null($this->value)) {
            return TRUE;
        }

        if (!is_string($this->value)) {
            return FALSE;
        }

        $result = preg_match($this->pattern, $this->value);
        if (FALSE === $result) {
            throw new Exception(sprintf('Regular expression failed.'));
        }
        return (bool) $result;
    }
}

然后,您可以为验证器编写单元测试。然后您就知道验证器有效,您可以随意使用它。

class Test {

    private $_optionalValue = null;

    /**
     * @var Validator
     */
    private $_validator;

    public function __construct(Validator $validator) {
        $this->_validator = $validator;
    }

    function setValue(String $optionalValue)
    {
        if (!$this->validator->isValid($optionalValue)) {
            throw new InvalidArgumentException(sprintf('Invalid value "%s".', $optionalValue));
        }
        $this->_optionalValue = $optionalValue;
    }
}