I extended Minds solution a bit:
public function seeException($callback, $exception = 'Exception', $message = '')
{
$function = function () use ($callback, $exception) {
try {
$callback();
return false;
}
catch (Exception $e) {
if (get_class($e) == $exception or get_parent_class($e) == $exception) {
return true;
}
return false;
}
};
$this->assertTrue($function(), $message);
}
In your cepts you can
$I->seeException('Laracasts\Validation\FormValidationException', function() use ($I){
//All actions that you expect to generate the Exception
$I->amOnPage('/users/edit/1');
$I->fillField('name', '');
$I->click('Update');
})
This way there is no need for assertTrue outside of the exception test method. You can also leave out the second argument if it is fine for you too know that an exception is thrown. Last you can put an message string as third argument. That way you can make the error more expressive if it fails.
EDIT
Pardon, I missed one thing. In FunctionalHelper.php you have to extends the parents _beforeSuite method:
public function _beforeSuite()
{
parent::_beforeSuite();
$this->assert = $this->getModule('Asserts');
}
EDIT2
Just found out that the test method doesn't work if you implicitly assert that an exception is thrown and php's native exception isn't the appearing exceptions parent because the method only checks first and second exception level. To make the method inspect the whole expection stack you have to use this method
public function assertThrows($callback, $exception = 'Exception', $message = '')
{
$function = function () use ($callback, $exception) {
$getAncestors = function($e) {
for ($classes[] = $e; $e = get_parent_class ($e); $classes[] = $e);
return $classes;
}
try {
$callback();
return false;
}
catch (Exception $e) {
if (get_class($e) == $exception or in_array($e, $getAncestors($e))) {
return true;
}
return false;
}
};
$this->assertTrue($function(), $message);
}