【问题标题】:Java convert from one exception to anotherJava 从一个异常转换为另一个
【发布时间】:2017-05-31 07:08:25
【问题描述】:

我有一个公共项目,其中包含一些正在另一个项目中使用的共享代码。我正在尝试将常见项目CommonException 中的异常转换/映射为一种新类型的异常,我们称之为SuperAwesomeException

我们的目标是有一种通用的方式来处理项目中的所有自定义异常。

我尝试使用UncaughtExceptionHandler 来执行此操作。这似乎在运行项目时有效,但在 JUnit 中无效,因为这将每个测试包装在一个 try/catch 块中,如 here 所述。

public final class ExceptionHandler implements Thread.UncaughtExceptionHandler {        
    @Override
    public void uncaughtException(Thread thread, Throwable exception) {            
        if (exception instanceof CommonException) {
            throw new SuperAwesomeException(exception.getMessage());
        }
        if (exception instanceof SuperAwesomeException) {
            throw new CommonException(exception.getMessage());
        }
        else {
            System.out.println("ERROR! caught some other exception I don't really care about");
            System.out.println("Not doing anything");    
        }
    }
}

是否有另一种方法可以从一个异常映射到另一个异常,或者我可以以某种方式告诉 JUnit 不要捕获某些异常并检查异常是否映射到正确的异常?

更新 - 我最初是如何尝试编写测试的:

public class ClassThatThrowsException {
    ClassThatThrowsException() {
        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
    }

    public void doSomething() {
        throw new CommonException("Something boring blew up!");
    }
}

public class ClassThatThrowsExceptionTest {    
    @Test(expected=SuperAwesomeException.class)
    public void testAwesome() {
        ClassThatThrowsException c = new ClassThatThrowsException();
        c.doSomething();
    }
}

抛出:

java.lang.Exception: Unexpected exception, expected<SuperAwesomeException> but was<CommonException>

【问题讨论】:

  • 如果您向下滚动该答案,您将找到Unit test should test your code, not JVM specification。为什么在单元测试中需要这样的规范?单元测试通常被视为通过/失败之类的事情。
  • 您应该将第一个exception 保留为新的cause。只需复制消息,您就可以摆脱堆栈跟踪,丢弃有用的信息。
  • @TimBiegeleisen 我正在尝试测试我的代码。我想测试在某些情况下会抛出异常。但我想将常见异常映射到该项目的更具体的异常。

标签: java unit-testing exception junit exception-handling


【解决方案1】:

问题是:当您使用 JUnit 时,框架 会捕获您的异常。因此 uncaught 异常处理程序一开始就没有被调用!

更多详情请见here

因此,你必须做两件事

A) 编写测试以确保您的异常处理程序实现按预期工作

@Test(expected=SuperAwesomeException.class)
public void testAwesome() {
   new ExceptionHandler().uncaughtException(null, new CommonException("whatever"));
}

B) 最管道 - 你要确保这个特定的未捕获处理程序实际上是由你的代码设置的:

@Test
public void testDefaultHandlerIsSet() {
   // creating a new instance should update the handler!
   new ClassThatThrowsException();
   Thread.UncaughtExceptionHandler handler = Thread.getDefaultUncaughtExceptionHandler();
   assertThat(handler, not(nullValue()));
   assertThat(handler, instanceOf(ExceptionHandler.class));
}

最后 - 请注意:你应该只做new XException(oldException.getMessage)。而是选择new XException("some message, oldException)

换句话说:你在这里找到了一个原因;所以你最好在你打算抛出的新异常中使用传入的异常作为原因。否则,您将丢失所有堆栈跟踪信息。

【讨论】:

  • 感谢您的回答。我已经更新了我的问题,说明我是如何尝试编写测试的,但不幸的是,由于 JUnit 捕获了第一个异常而不是让它被 ExceptionHandler 转换,所以我的测试失败了有没有一种方法可以让我的测试工作而无需更改预计是Exception 并捕捉所有感觉有点hacky的东西。
  • 我喜欢你的测试并将添加一些类似于我的测试套件的东西。我只是在考虑所有其他会抛出 JUnit 当前正在破坏的异常的测试。
  • 我仔细查看了您的示例并发现了您的问题。我认为正在解决您的所有问题;现在让我们希望你同意并赞成/接受......因为在这里花了很长时间;-)
猜你喜欢
  • 1970-01-01
  • 2013-12-03
  • 1970-01-01
  • 2022-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-10
  • 1970-01-01
相关资源
最近更新 更多