这种新的
Java 7 try-with-resources构造是相当不错的.或者至少,这是很好,直到一个例外来了,毁了我的一天.
我终于设法把它烧成一个可重复的测试,它只使用JUnit jMock.
@Test public void testAddSuppressedIssue() throws Exception { Mockery mockery = new Mockery(); final Dependency dependency = mockery.mock(Dependency.class); mockery.checking(new Expectations() {{ allowing(dependency).expectedCall(); allowing(dependency).close(); }}); try (DependencyUser user = new DependencyUser(dependency)) { user.doStuff(); } } // A class we're testing. private static class DependencyUser implements Closeable { private final Dependency dependency; private DependencyUser(Dependency dependency) { this.dependency = dependency; } public void doStuff() { dependency.unexpectedCall(); // bug } @Override public void close() throws IOException { dependency.close(); } } // Interface for its dependent component. private static interface Dependency extends Closeable { void expectedCall(); void unexpectedCall(); }
运行这个例子,我得到:
java.lang.IllegalArgumentException: Self-suppression not permitted at java.lang.Throwable.addSuppressed(Throwable.java:1042) at com.acme.Java7FeaturesTest.testTryWithResources(Java7FeaturesTest.java:35)
阅读文档,他们似乎在说,如果要将抑制异常添加到自身,那就是触发此错误.但是我没有这样做,我只是使用一个资源块尝试. Java编译器然后生成似乎是非法代码,这使得该功能无法使用.
当然,当测试通过时,不会发生问题.当测试失败时,会发生异常.所以现在我已经解决了我最初发现我已经恢复使用try-with-resources的问题.但是下一次发生异常时,我宁愿异常是期望失败,而不是一个Java本身已经发出似乎没有好的理由.
那么…有没有办法在这里得到适当的错误报告,而不放弃试用资源?
解决方法
看起来jMock从两个方法都抛出相同的异常实例.没有jMock就可以复制它:
public class Test implements Closeable { private RuntimeException ex = new RuntimeException(); public void doStuff() { throw ex; } public void close() { throw ex; } } try (Test t = new Test()) { t.doStuff(); }
如果是这样,我认为这是jMock而不是Java编译器的问题.