Since PHPUnit 3.2.0 the former extension for exception test case (PHPUnit_Extension_ExceptionTest) has been merged back into the default test case. This allows you to use setExpextedException() in a normal test case. A simple exception test looks like that:
<?php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
$this->setExpectedException('Exception');
throw new Exception();
}
/**
* @expectedException Exception
*/
public function testException2()
{
throw new Exception()
}
}
Often this is not enough. When you use a Zend Framework alike style for exceptions (one base class to rule them all) you often throw the same exception class with different messages. To test wheither the correct exception has been thrown, I discussed with Sebastian Bergmann about introducing an contains assertion for messages and this patch was applied. So in the current PHPUnit trunk you can test exception messages:
<?php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testException()
{
$this->setExpectedException('Exception', 'Exception message');
throw new Exception('Exception message');
}
/**
* @expectedException Exception Exception message
*/
public function testException2()
{
throw new Exception('Exception message')
}
}
As internally PHPUnit uses an assertContains for the exception message you can even test for incomplete strings like an exception message containing a random file name.
I proposed to do the same for exception codes but Sebastian did not agree. But let’s see, maybe that will change when Zend Framework is going to use exception codes a lot.
Filed under PHP, PHPUnit, Unit testing & five comments & one trackback
Trackback specific URI for this entry
Hey Lars,
nice idea – but let’s be honest – using Exception Messages is not really professional. Usually you should supply additional Information when throwing, to give more specific info – then your idea won’t work. I will discuss this with sebastian, I think he need to support the code – here you are 100% right. The Exception mechanism of ZF sucks, they will need to adopt it to something more useful.
Anyway – really nice idea :)
This is how I do test exceptions till now:
try { .... } catch( Swoodoo_Exception $e) { if( $e->getCode() == Swoodoo_Exception::ACCOUNT_INVALID_ID) return; // OK }
$this->fail();I’m not sure about the "professional". At the end professional is what works on the long term. Checking the message works pretty fine to distinguish between different exceptions of the same exception class.
Lars,
sorry if my comment was misleading – for sure I did not want to say that your idea is not professional – no way.
Only that testing the message is not the right way ;) – let me make an example. Wrong Input, Message could be "Field ‘Name’ must not have any numbers". This Message could be generated automatically for all "char only" fields only the field name changes.
If you work like this in a team then you can wait that somebody get the idea to test the message for the content e.g. "if strstr(mess,‘must not have a char’)" – and when you change the message e.g. for multilanguage reasons – then….
Of course there are scenarios where this does not work as expected. No doubt.
Trackback from WEBLOG (/usr/portage)
posted on January 18th 2008, 01:02:00 am Testing exceptions (2)As I previously mentioned we made some effort to better check exceptions. The target is not only ensuring that a various exception is thrown but also that this exception is really the one which is expected. The result was a patch for PHPUnit to test for