junit 预期错误_谨慎使用JUnit的预期异常
junit 預期錯誤
有時,當我們收到對jOOQ或其他庫的拉取請求時,人們會將單元測試中的代碼更改為更“慣用的JUnit”。 特別是,這意味著他們傾向于更改此代碼(公認的不是那么漂亮的代碼):
@Test public void testValueOfIntInvalid() {try {ubyte((UByte.MIN_VALUE) - 1);fail();}catch (NumberFormatException e) {}try {ubyte((UByte.MAX_VALUE) + 1);fail();}catch (NumberFormatException e) {} }…成為“更好”和“更清潔”的版本:
@Test(expected = NumberFormatException.class) public void testValueOfShortInvalidCase1() {ubyte((short) ((UByte.MIN_VALUE) - 1)); }@Test(expected = NumberFormatException.class) public void testValueOfShortInvalidCase2() {ubyte((short) ((UByte.MAX_VALUE) + 1)); }我們獲得了什么?
沒有!
當然,我們已經必須使用@Test批注,因此我們不妨使用其expected的屬性吧? 我聲稱這是完全錯誤的。 有兩個原因。 當我說“兩個”時,我的意思是“四個”:
1.在代碼行數方面,我們并沒有真正獲得任何好處
比較語義上有趣的位:
// This: try {ubyte((UByte.MIN_VALUE) - 1);fail("Reason for failing"); } catch (NumberFormatException e) {}// Vs this: @Test(expected = NumberFormatException.class) public void reasonForFailing() {ubyte((short) ((UByte.MAX_VALUE) + 1)); }給定或采用空格格式,基本語義信息量完全相同:
因此,即使從樣式角度來看,這也不是真正有意義的更改。
2.無論如何我們都必須將其重構
在注釋驅動的方法中,我所能做的就是測試異常類型 。 例如,在以后要添加更多測試的情況下,我無法對異常消息做出任何假設。 考慮一下:
// This: try {ubyte((UByte.MIN_VALUE) - 1);fail("Reason for failing"); } catch (NumberFormatException e) {assertEquals("some message", e.getMessage());assertNull(e.getCause());... }3.單一方法調用不是單位
單元測試稱為testValueOfIntInvalid() 。 因此, 通常在輸入無效的情況下,要測試的語義“單位”是UByte類型的valueOf()行為的語義“單位”。 不適用于單個值,例如UByte.MIN_VALUE - 1 。
不應將其拆分為更小的單元,僅僅是因為這是我們可以將@Test注釋刺入其功能范圍的唯一方法。
TDD伙計們,請聽聽。 我從不希望將我的API設計或我的邏輯塞進由“向后”測試框架(不是個人的,JUnit)強加的一些怪異的限制。 永不 ! “我的” API比“您的”測試重要100倍。 這包括我不想:
- 公開一切
- 使一切都沒有定論
- 使一切都可以注射
- 使所有內容均為非靜態
- 使用注釋。 我討厭注解。
不。 你錯了。 Java已經不是一種太復雜的語言,但是讓我至少可以使用我想要的任何方式使用它提供的一些功能。
不要因為測試而在我的代碼上強加您的設計或語義上的毀損。
好。 我React過度了。 我總是在帶有批注的情況下 。 因為…
4.對于控制流結構而言,注釋始終是錯誤的選擇
一次又一次,我為Java生態系統中的注釋濫用而感到驚訝。 注釋對于三件事有好處:
并且要注意,@ @Transactional是使其成為主流的少數幾個真正有用的方面之一(日志掛鉤是另一個方面,或者,如果絕對必須的話,可以進行依賴注入)。 在大多數情況下,AOP是解決問題的利基技術,您通常在普通程序中不希望這樣做。
用注解對控制流結構進行建模絕對不是一個好主意,更不用說測試行為了
是。 Java已經采用了很長的(緩慢的)方法來包含更復雜的編程習慣。 但是,如果您對單元測試中偶爾的try { .. } catch { .. }語句的冗長內容感到不滿,那么您可以找到解決方案。 是Java 8。
如何用Java 8更好地做
JUnit lambda正在開發中: http : //junit.org/junit-lambda.html
他們將新的功能性API添加到新的Assertions類中: https : //github.com/junit-team/junit-lambda/blob/master/junit5-api/src/main/java/org/junit/gen5/api /Assertions.java
一切都基于Executable功能接口 :
@FunctionalInterface public interface Executable {void execute() throws Exception; }該可執行文件現在可以用于實現斷言引發(或不引發)異常的代碼。 請參見Assertions的以下方法
public static void assertThrows(Class<? extends Throwable> expected, Executable executable) {expectThrows(expected, executable); }public static <T extends Throwable> T expectThrows(Class<T> expectedType, Executable executable) {try {executable.execute();}catch (Throwable actualException) {if (expectedType.isInstance(actualException)) {return (T) actualException;}else {String message = Assertions.format(expectedType.getName(), actualException.getClass().getName(),"unexpected exception type thrown;");throw new AssertionFailedError(message, actualException);}}throw new AssertionFailedError(String.format("Expected %s to be thrown, but nothing was thrown.", expectedType.getName())); }而已! 現在,那些反對try { .. } catch { .. }塊的冗長的人可以重寫此代碼:
try {ubyte((UByte.MIN_VALUE) - 1);fail("Reason for failing"); } catch (NumberFormatException e) {}…進入:
expectThrows(NumberFormatException.class, () -> ubyte((UByte.MIN_VALUE) - 1));如果我想對異常進行進一步檢查,可以這樣做:
Exception e = expectThrows(NumberFormatException.class, () -> ubyte((UByte.MIN_VALUE) - 1)); assertEquals("abc", e.getMessage()); ...出色的工作,JUnit lambda團隊!
函數式編程每次都會擊敗注釋
注釋被濫用了很多邏輯 ,主要是在JavaEE和Spring環境中,它們都非常渴望將XML配置移回Java代碼。 這是錯誤的方法,這里提供的示例清楚地表明,與使用批注相比,幾乎總是有一種更好的方法可以使用面向對象或功能編程來顯式地寫出控制流邏輯。
在@Test(expected = ...)的情況下,我得出結論:
安息, expected
(無論如何,它不再是JUnit 5 @Test批注的一部分)
翻譯自: https://www.javacodegeeks.com/2016/01/use-junits-expected-exceptions-sparingly.html
junit 預期錯誤
總結
以上是生活随笔為你收集整理的junit 预期错误_谨慎使用JUnit的预期异常的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试如何防止被骗方案(面试如何防止ddo
- 下一篇: 教资小学备案要多久(教资小学备案)