在catch块中设置对象属性时,PHPUnit测试失败

时间:2012-12-03 20:08:26

标签: php zend-framework object phpunit try-catch

我正在测试setSubject方法,该方法设置为(空主题)(如果缺少)。 如果尝试访问未声明的属性,Zend_Mail会抛出异常(例如,电子邮件主题丢失,最好抛出一些例外)。更多信息:http://framework.zend.com/issues/browse/ZF-11371 这是我需要使用才能成功测试它:

protected function setSubject()
{
    # catch exception thrown if non existing $this->message object property is accessed
    try
    {
      $this->subject = $this->defunctTheContent($this->message->getHeaders(), $this->message->subject);
    }
    catch (Zend_Mail_Exception $e)
    {
    }
    if( ! $this->subject)
      $this->subject = '(empty subject)';
}

测试

public function testNoSubject()
{
  $email = new parseEmail(file_get_contents('mail.x'));
  $this->AssertEquals('(empty subject)', $email->subject);
}

但是,如果我尝试使用此代码,您可以看到catch块为空...

protected function setSubject()
{
    try
    {
      $this->subject = $this->defunctTheContent($this->message->getHeaders(), $this->message->subject);
    }
    catch (Zend_Mail_Exception $e)
    {
      $this->subject = '(empty subject)';
    }
}

测试失败并显示消息:

  

有1个错误:

     

1)Email_ParseTest :: testNoSubject   InvalidArgumentException:subject是必需的

它抱怨$ this->主题未设置(或类似)。

更多信息:

  • PHP 5.4.8
  • Zend Framework 1.9.5
  • PHPUnit 3.6.12
  • subject被定义为空字符串(""

我已经“手动”测试了第二种方法,它按预期工作(主题在catch块中设置)。我对PHPUnit没有多少经验,所以这可能很容易E_PEBKAC

2 个答案:

答案 0 :(得分:3)

除非我误解你的问题,否则你试图测试受保护的方法......你不能这样做。假设通过测试使用它们的公共方法来测试受保护和私有方法。

如果你在PHPUnit中使用PHP 5.3.2+,你可以在运行测试之前使用反射将它们设置为公开来直接测试你的私有和受保护的方法,但是,正如我所提到的,你'重新考虑测试公共方法。

但是如果你想使用反射,这是一个通用的例子:

protected static function getMethod($name) {
  $class = new ReflectionClass('MyClass');
  $method = $class->getMethod($name);
  $method->setAccessible(true);
  return $method;
}

public function testFoo() {
  $foo = self::getMethod('foo');
  $obj = new MyClass();
  $foo->invokeArgs($obj, array(...));
  ...
}

答案 1 :(得分:1)

看起来你正在捕捉错误的异常:Zend_Mail似乎抛出一个InvalidArgumentException,而你却抓住了Zend_Mail_Exception

请尝试以下代码:

protected function setSubject()
{
    # catch exception thrown if non existing $this->message object property is accessed
    try {
        $this->subject = $this->defunctTheContent($this->message->getHeaders(), $this->message->subject);
    }
    catch (InvalidArgumentException $e) {
        $this->subject = '(empty subject)';
    }
}

修改

再次阅读你的问题,我会说永远不会抛出Zend_Mail_Exception。 如果您从第一个代码块中删除try / catch,我敢打赌它也能正常运行:

protected function setSubject()
{
    $this->subject = $this->defunctTheContent($this->message->getHeaders(), $this->message->subject);
    if (! $this->subject) {
        $this->subject = '(empty subject)';
    }
}

Line 396指的是一个不存在的标头,但即使$this->subject为空(例外类&消息与您的测试结果不匹配),它看起来也不会被触发。我怀疑此标头已在之前,Zend或其他地方设置为空值。

这可以解释为什么在第二种情况下,永远不会设置$this->subjectcatch代码永远不会被执行)。 InvalidArgumentException类可能会引发parseEmail,它会检测到subject未设置。

然而,第二个块无条件地检查! $this->subject,并相应地设置它。所以考试通过了。

总结:

  • Zend_Mail_Exception永远不会被抛出
  • {li> InvalidArgumentExceptionparseEmail 抛出