标签: nested-exceptions

检查某个异常类型是否是嵌套异常中的原因(原因等等)的最佳方法?

我正在编写一些JUnit测试,以验证是否抛出了类型MyCustomException的异常.但是,此异常多次包含在其他异常中,例如在InvocationTargetException中,而InvocationTargetException又包含在RuntimeException中.

什么是确定MyCustomException是否以某种方式导致我实际捕获的异常的最佳方法?我想做这样的事情(见下划线):


try {
    doSomethingPotentiallyExceptional();
    fail("Expected an exception.");
} catch (RuntimeException e) {
     if (!e.wasCausedBy(MyCustomException.class)
        fail("Expected a different kind of exception.");
}
Run Code Online (Sandbox Code Playgroud)

我想避免getCause()深入调用一些"层",以及类似的丑陋工作.有更好的方法吗?

(显然,Spring有NestedRuntimeException.contains(Class),它可以做我想要的 - 但我没有使用Spring.)

CLOSED: 好的,我猜有一个实用方法真的没有绕过:-)感谢所有回复的人!

java spring exception-handling exception nested-exceptions

26
推荐指数
3
解决办法
3万
查看次数

Catching an exception that is nested into another exception

I want to catch an exception, that is nested into another exception. I'm doing it currently this way:

} catch (RemoteAccessException e) {
    if (e != null && e.getCause() != null && e.getCause().getCause() != null) {
        MyException etrp = (MyException) e.getCause().getCause();
        ...
    } else {
        throw new IllegalStateException("Error at calling service 'service'");
    }
}
Run Code Online (Sandbox Code Playgroud)

Is there a way to do this more efficient and elegant?

java exception try-catch nested-exceptions

26
推荐指数
4
解决办法
4万
查看次数

为什么C++不使用std :: nested_exception来允许从析构函数中抛出?

从析构函数抛出异常的主要问题是,在析构函数被调用的那一刻,另一个异常可能是"在飞行中"(std::uncaught_exception() == true),因此在这种情况下做什么并不明显.用新的"覆盖"旧的异常将是处理这种情况的可能方法之一.但是决定在这种情况下必须调用std::terminate(或其他std::terminate_handler).

C++ 11通过std::nested_exception类引入了嵌套异常功能.该特征可用于解决上述问题.旧(未捕获)异常可能只是嵌套到新异常中(反之亦然?)然后可能抛出嵌套异常.但是没有使用这个想法.std::terminate在C++ 11和C++ 14中仍然会出现这种情况.

所以问题.是否考虑过嵌套异常的想法?它有什么问题吗?是不是在C++ 17中会改变这种情况?

c++ exception-handling exception nested-exceptions c++11

16
推荐指数
2
解决办法
5113
查看次数

使用RAII嵌套异常

所以在C++中嵌套异常的方法std::nested_exception是:

void foo() {
  try {
    // code that might throw
    std::ifstream file("nonexistent.file");
    file.exceptions(std::ios_base::failbit);
  }

  catch(...) {
    std::throw_with_nested(std::runtime_error("foo failed"));
  }
}
Run Code Online (Sandbox Code Playgroud)

但是这种技术在每个级别使用显式的try/catch块,希望嵌套异常,这至少可以说是丑陋的.

Jon Kalb扩展为"责任获取是初始化"的RAII,是处理异常而不是使用显式try/catch块的更清晰的方法.使用RAII,显式try/catch块主要仅用于最终处理异常,例如,为了向用户显示错误消息.

查看上面的代码,在我看来,输入foo()可以被视为有责任报告任何异常,std::runtime_error("foo failed")并将细节嵌套在嵌套异常中.如果我们可以使用RAII来获得这个责任,那么代码看起来会更清晰:

void foo() {
  Throw_with_nested on_error("foo failed");

  // code that might throw
  std::ifstream file("nonexistent.file");
  file.exceptions(std::ios_base::failbit);
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在这里使用RAII语法来替换显式的try/catch块?


为此,我们需要一种类型,当它的析构函数被调用时,检查析构函数调用是否是由异常引起的,如果是,则嵌套该异常,并抛出新的嵌套异常,以便正常地展开.这可能看起来像:

struct Throw_with_nested {
  const char *msg;

  Throw_with_nested(const char *error_message) : msg(error_message) {}

  ~Throw_with_nested() {
    if (std::uncaught_exception()) {
      std::throw_with_nested(std::runtime_error(msg));
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

但是,std::throw_with_nested()要求"当前处理的异常"处于活动状态,这意味着除了catch块的上下文之外它不起作用.所以我们需要这样的东西:

  ~Throw_with_nested() {
    if (std::uncaught_exception()) {
      try …
Run Code Online (Sandbox Code Playgroud)

c++ exception raii nested-exceptions c++11

12
推荐指数
1
解决办法
598
查看次数

是否应该在C++中链接异常?

我刚刚完成了一个C++程序,我已经实现了自己的异常(虽然派生自std :: exception).当一个异常导致连锁反应,向上传播错误并引起其他异常时,我应用的做法是在模块的每个适当步骤(读取类)中连接错误消息.即旧的异常本身被删除并创建一个新的异常,但是有一个更长的错误消息.

这可能适用于我的小程序,但我最终对我的方法不太满意.例如,除最后一个异常外,不保留行号(虽然目前不应用)和文件名; 实际上,在第一个例外中,这些信息最受关注.

我认为通过将异常链接在一起可以更好地处理这个问题; 即在新异常的构造函数中提供旧异常.但是如何实施呢?当它们超出方法的范围时,异常是否会死亡,从而阻止使用异常指针?如果异常可以是任何派生类,如何复制和存储异常?

这最终促使我考虑在C++中链接异常是否是一个好主意.也许应该只创建一个异常然后添加额外的数据(就像我一直在做的那样,但可能会以更好的方式)?

你对此有何回应?是否应将由另一个引起的异常链接在一起以保留某种"异常追踪" - 以及如何实施? - 或者是否应该使用单个例外并附加其他数据 - 应该如何做?

c++ exception chaining nested-exceptions

10
推荐指数
2
解决办法
1834
查看次数

如何将 dynamic_cast 从 std::exception 转换为 std::nested_exception?

例如,我刚刚看到了一个包含 dynamic_cast from std::exceptionto的代码std::nested_exception

try {
    std::throw_with_nested(std::runtime_error("error"));
} catch (std::exception &e) {
    auto &nested = dynamic_cast<std::nested_exception&>(e);
    std::cout << "ok" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

第一次,我认为这段代码不会被编译,因为std::nested_exception不是派生std::exception,我希望dynamic_cast会对继承进行静态检查,但我错了。

虽然我找不到明确提到dynamic_cast允许这样做的相关标准规范,但我确认所有三个主要编译器(clang/gcc/msvc)都允许dynamic_cast完全不相关的类型。

但是,仍然std::nested_exception不是从 派生的std::exception,所以我认为dynamic_cast将抛出bad_alloc异常并且"ok"永远不会打印。我又错了。

现在,我想知道这是如何工作的。这对std::exceptionand 来说有什么特别的和特殊的std::nested_exception吗?或者,我可以dynamic_cast<A&>(b)A对象的类型和类型b没有公共基类的情况下取得另一个成功吗?

c++ dynamic-cast exception nested-exceptions c++11

3
推荐指数
1
解决办法
561
查看次数

Junit5:预期嵌套异常

JUnit 5 如何允许检查嵌套异常?我正在寻找类似于在 JUnit 4 中借助 a 可以完成的操作@org.junit.Rule,如以下代码片段所示:

class MyTest {

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Test
    public void checkForNestedException() {

        // a JPA exception will be thrown, with a nested LazyInitializationException
        expectedException.expectCause(isA(LazyInitializationException.class));

        Sample s = sampleRepository.findOne(id);

        // not touching results triggers exception
        sampleRepository.delete(s);
    }
}
Run Code Online (Sandbox Code Playgroud)

根据评论编辑:

Assertions.assertThrows(LazyInitializationException.class)在 JUnit 5 中不起作用,因为LazyInitializationException是 的嵌套异常(原因)JpaSystemException

只能检查外部异常,这不能按预期工作:

// assertThrows does not allow checking for nested LazyInitializationException
Assertions.assertThrows(JpaSystemException.class, () -> {

    Sample s = sampleRepository.getOne(id);

    // not …
Run Code Online (Sandbox Code Playgroud)

nested-exceptions junit5

2
推荐指数
1
解决办法
1686
查看次数