15

这个新的 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)

阅读文档,他们似乎在说,如果您要向自身添加一个抑制的异常,那就是触发此错误的原因。但没有这样做,只是在使用 try-with-resources 块。Java 编译器然后生成看似非法的代码,这使得该功能实际上无法使用。

当然,当测试通过时,不会出现问题。而当测试失败时,就会发生异常。所以现在我已经解决了我最初发现的问题,我已经恢复使用 try-with-resources。但是下次发生异常时,我更希望异常是期望失败,而不是一个 Java 本身似乎没有充分的理由发出。

那么......有没有办法在这里得到正确的错误报告,而不放弃尝试资源?

4

2 回答 2

7

看起来 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 编译器的问题。

于 2012-08-24T05:51:08.490 回答
0

我在Apache Commons VFS中遇到了问题(Java 8 上的单元测试失败,请参阅VFS-521)。事实证明,java.io.FilterOutputStream 正在使用 try-with-resource(抑制异常)功能它无法处理抛出相同异常的刷新 + 关闭。

更糟糕的是,在 Java 8 之前它只是默默地从flush()调用中吞下异常,请参阅JDK-6335274)。

我通过完全避免 super.close() 来修复它。目前在 corelibs-dev openjdk mailingl 上讨论这个问题:http: //openjdk.5641.n7.nabble.com/FilterOutputStream-close-throws-exception-from-flush-td187617.html

于 2014-05-02T23:13:36.833 回答