对于几乎所有的情况,您都应该抛出一个新的异常并附加旧的异常。没有必要让事情复杂化。
try {
dodgyCode();
}
catch(\Exception $oldException) {
throw new \Exception('My extra information', 0, $oldException);
}
不过,每隔一段时间,您实际上确实需要就地操作一个异常,因为抛出另一个异常实际上并不是您想要做的。
一个很好的例子是Behat https://github.com/Behat/Behat FeatureContext
当您想在其中附加附加信息时@AfterStep
方法。步骤失败后,您可能希望截取屏幕截图,然后在输出中添加一条消息,说明在哪里可以看到该屏幕截图。
因此,为了更改异常的消息,您可以替换它,并且不能抛出新的异常,您可以使用反射来暴力破解参数值:
$message = " - My appended message";
$reflectionObject = new \ReflectionObject($exception);
$reflectionObjectProp = $reflectionObject->getProperty('message');
$reflectionObjectProp->setAccessible(true);
$reflectionObjectProp->setValue($exception, $exception->getMessage() . $message);
这是上下文中的 Behat 示例:
/**
* Save screen shot on failure
* @AfterStep
* @param AfterStepScope $scope
*/
public function saveScreenShot(AfterStepScope $scope) {
if (!$scope->getTestResult()->isPassed()) {
try {
$screenshot = $this->getSession()->getScreenshot();
if($screenshot) {
$filename = $this->makeFilenameSafe(
date('YmdHis')."_{$scope->getStep()->getText()}"
);
$filename = "{$filename}.png";
$this->saveReport(
$filename,
$screenshot
);
$result = $scope->getTestResult();
if($result instanceof ExceptionResult && $result->hasException()) {
$exception = $result->getException();
$message = "\nScreenshot saved to {$this->getReportLocation($filename)}";
$reflectionObject = new \ReflectionObject($exception);
$reflectionObjectProp = $reflectionObject->getProperty('message');
$reflectionObjectProp->setAccessible(true);
$reflectionObjectProp->setValue($exception, $exception->getMessage() . $message);
}
}
}
catch(UnsupportedDriverActionException $e) {
// Overly specific catch
// Do nothing
}
}
}
再次强调,如果可以避免的话,绝对不应该这样做。
Source: 我的老老板 http://blog.loftdigital.com/take-screenshot-with-behat-after-failed-step