私はまた閉じる必要があるいくつかのリソースを作成するいくつかのjunitテストがあります。
このロジックを実装する1つの方法は、@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のassertキーワードがError
- ではないException
。
try-with-resourceは「キャッチ」しますかError
そしてcloseメソッドを呼び出しますか?
*で答えが見つかりませんでしたtry-with-resourcesのドキュメント。
ありませんcatch
何でも。しかしそれはするfinally
すべてのリソースを閉じます。
finally
ブロックErrorが投げられても実行される。
finally
ブロックします。 - ThiloSystem.exit()
:stackoverflow.com/questions/14905006/… - Christophe Roussyfinally
ブロックと同じように、finally
ブロックすると、それ以降のすべてがキャッチされます。Throwable
のsclose()
操作を追加し、抑制された1次スロー可能へのスロー可能。 Afinally
それがあるならば、blockはそれが一次投棄物についての知識を持っていないのでそれをすることができません。 - Holgerfinally
ブロック加えてへcatch
実際には何もキャッチしないブロック(ただ一次スロー可能オブジェクトを記録して再スローするだけです)。すべての「アクション」 finallyブロックで発生します。詳細は@Nicolasの回答を見てください。 - Thilo
基本の擬似コードリソースを使ってみるステートメントは(cfJava 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
当然のことながら、現在実行中のJava仮想マシンは終了します。Error
またはのサブクラスThrowable
スローされます。
javac
文字通り、この複雑な形式仕様に従います。考えてfinally
2つのケースではコードの複製を介して最終的に実装されていますが、例外を変数に格納し、それに対してテストすることはまったく意味がありません。null
例外があるかどうかにかかわらず、コードパスで既に暗黙のうちに暗示されている場合… - Holgerfinally
ブロックは、例外があったかどうかにかかわらず実行されます。どのようなコードの重複を意味しますか。Identifier.close()
そしてそれはなぜあなたを悩ませるのですか? try-with-resourcesで代わりに何をすべきですか? - siegifinally
機能、したがって、finally
ブロックは、そのブロックを離れる可能性のあるすべてのコードパスにアクションをコピーし、さらに例外ハンドラを追加することによってコンパイルされます。try { foo(); } finally { bar(); }
にコンパイルされますtry { foo(); } catch(Throwable t) { bar(); throw t; } bar();
複製するbar()
呼び出しコードそこでは、例外が発生したか否か、すなわち最初のものがコードパスによって暗示される。bar();
呼び出しは例外的な条件下でのものであり、2番目はなしのものです。 - Holgerjavac
この結果として、で議論されています。この質問。私の答えでは、私はこの振る舞いを「javac
命名せずに「内部的に動作します」finally
この時点では正式な仕様がわからなかったからといって単純にブロックすることができますが、それを見れば、物事は完全に明確になります(そして一般的な記述は依然として有効です)。 - Holgerjavac
しかし単に" desugar"すること。それは言語仕様に従ってそれからJITコンパイラにその仕事をさせます。 - siegi
リソースを使ってみても、自分自身では何も捉えられません。
しかし、あなたは添付することができますcatch
try-with-resourcesブロックの最後までブロックします。Throwable
あなたが好きです:
try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
// ... Whatever
} catch (RuntimeException e) {
// Handle e.
} catch (Exception | Throwable t) {
// Handle t.
}
背後にあるアイデアtry-with-resources
リソースが閉じられるべきであることを確認することです。
従来の問題try-catch-finally
文はあなたのことを想定しましょうtry
blockは例外をスローします。通常は、その例外を次のように処理します。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()
methodも例外を生成しました。その例外は自動的に抑制されます。
また見なさい:Java言語仕様14.20.3
あなたの側での誤解:try-with-resourcesはしますではないするキャッチ。
それはする最後の 最後にしたがって、「問題」の種類は関係ありません。
を参照してくださいJLS詳細については!