我有一些junit测试可以创建一些也应该关闭的资源。
实现此逻辑的一种方法是使用@Before
和@After
方法。
我所做的是将创建封装在某个实用程序类中以供重用。例如:
class UserCreatorTestUtil implements AutoClosable {
User create() {...}
void close() {...}
}
关键是对象要关闭,而不是需要记住在@After
中关闭它。
用法应为:
@Test
void test() {
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
User user = userCreatorTestUtil.create();
// Do some stuff regarding the user's phone
Assert.assertEquals("123456789", user.getPhone());
}
}
问题是junit的断言关键字会引发Error
- 而不是Exception
。
try-with-resource" catch" Error
并调用close方法?
*无法在try-with-resources documentation中找到答案。
答案 0 :(得分:75)
它没有catch
任何东西。但它会finally
关闭所有资源。
finally
阻止are run even when an Error is thrown。
答案 1 :(得分:37)
基本 try-with-resources 语句的伪代码是(cf Java Language Specification §14.20.3.1
):
final VariableModifiers_minus_final R Identifier = Expression;
Throwable #primaryExc = null;
try ResourceSpecification_tail
Block
catch (Throwable #t) {
#primaryExc = #t;
throw #t;
} finally {
if (Identifier != null) {
if (#primaryExc != null) {
try {
Identifier.close();
} catch (Throwable #suppressedExc) {
#primaryExc.addSuppressed(#suppressedExc);
}
} else {
Identifier.close();
}
}
}
正如您所看到的那样,Throwable
不会Exception
包含Error
,而只会获取主要异常,以便将任何例外添加为已抑制的例外关闭资源时发生的事情。
您还可以注意到finally
块中的资源已关闭,这意味着无论发生什么情况都会关闭(当然System.exit
除外即使在抛出Error
或任何Throwable
子类的情况下,它也会终止当前运行的Java虚拟机。
答案 2 :(得分:13)
尝试资源不会捕获任何内容。
但是,您可以将catch
块附加到try-with-resources块的末尾,以捕获您喜欢的任何类型的Throwable
:
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
// ... Whatever
} catch (RuntimeException e) {
// Handle e.
} catch (Exception | Throwable t) {
// Handle t.
}
答案 3 :(得分:9)
try-with-resources
背后的想法是确保资源应该关闭。
传统try-catch-finally
语句的问题在于,假设您的try
块抛出异常;现在通常你会在finally
块中处理该异常。
现在假设finally块中也发生异常。在这种情况下,try catch抛出的异常是丢失,finally
块中生成的异常会被传播。
try {
// use something that's using resource
// e.g., streams
} catch(IOException e) {
// handle
} finally {
stream.close();
//if any exception occurs in the above line, than that exception
//will be propagated and the original exception that occurred
//in try block is lost.
}
在try-with-resources
中,资源的close()
方法会自动调用,如果close()
抛出任何异常,则finally
的其余部分不会被触发到了,原来的例外就丢失了。
与此对比:
try (InputStream inputStream= new FileInputStream("C://test.txt")){
// ... use stream
} catch(IOException e) {
// handle exception
}
在上面的代码段中,自动调用close()
方法,如果close()
方法也生成了任何异常,则该异常将自动被抑制。
答案 4 :(得分:5)