Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHPUnit test fails when setting object property within catch block

I'm testing setSubject method which sets subject to (empty subject) if it is missing. Zend_Mail throws exception if undeclared property is trying to be accessed (e.g. email subject is missing, better throw some exceptions). More info: http://framework.zend.com/issues/browse/ZF-11371 This is what I need to use to be able to test it successfully:

Class

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)';
}

Test

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

However, you can see that catch block is empty, if I try this code...

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

Test fails with message:

There was 1 error:

1) Email_ParseTest::testNoSubject InvalidArgumentException: subject is required

It complains that $this->subject is not set (or similar).

Some more info:

  • PHP 5.4.8
  • Zend Framework 1.9.5
  • PHPUnit 3.6.12
  • subject is defined as empty string ("")

I've tested second method "by hand", and it is working as expected (subject is set within catch block). I don't have much experience with PHPUnit so this might be E_PEBKAC easily.

like image 538
Dejan Marjanović Avatar asked Dec 03 '12 20:12

Dejan Marjanović


1 Answers

Unless i'm misunderstanding your question, you're attempting to test a protected method... you can't do that this way. Protected and private methods are suppose to be tested by testing the public methods that use them.

If you're using PHP 5.3.2+ with PHPUnit, you can test your private and protected methods directly by using reflection to set them to be public prior to running your tests, however, as I've mentioned, you're suppose to test public methods.

But if you want to use reflection, here's a generic example:

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(...));
  ...
}
like image 158
jsteinmann Avatar answered Oct 02 '22 19:10

jsteinmann