久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

如何驗證沒有拋出異常

How to verify that an exception was not thrown(如何驗證沒有拋出異常)
本文介紹了如何驗證沒有拋出異常的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

在我使用 Mockito 的單元測試中,我想驗證 NullPointerException 沒有被拋出.

In my unit test using Mockito I want to verify that NullPointerException was not thrown.

public void testNPENotThrown{
    Calling calling= Mock(Calling.class);
    testClass.setInner(calling);
    testClass.setThrow(true);

    testClass.testMethod();

    verify(calling, never()).method();
}

我的測試設置了 testClass,設置了 Calling 對象和屬性,以便該方法將拋出 NullPointerException.

My test set up the testClass, setting the Calling object and the property so that the method will throw a NullPointerException.

驗證 Calling.method() 從未被調用.

I verify that the Calling.method() is never called.

public void testMethod(){
    if(throw) {
        throw new NullPointerException();
    }

    calling.method();
}

我想要一個失敗的測試,因為它拋出一個 NullPointerException,然后我想編寫一些代碼來解決這個問題.

I want to have a failing test because it throws a NullPointerException, and then I want to write some code to fix this.

我注意到的是測試總是通過,因為測試方法永遠不會拋出異常.

What I have noticed is that the test always passes as the exception is never thrown up the the test method.

推薦答案

tl;dr

  • JDK8 后:使用 AssertJ 或自定義 lambda 來斷言 異常 行為.

  • post-JDK8 : Use AssertJ or custom lambdas to assert exceptional behaviour.

pre-JDK8 :我會推薦舊的好 try-catch 塊.(別忘了在 catch 塊之前添加一個 fail() 斷言)

pre-JDK8 : I will recommend the old good try-catch block. (Don't forget to add a fail() assertion before the catch block)

無論是 Junit 4 還是 JUnit 5.

長篇大論

可以自己編寫一個自己動手 try-catch 塊或使用JUnit 工具(@Test(expected = ...)@Rule ExpectedException JUnit 規則特性).

It is possible to write yourself a do it yourself try-catch block or use the JUnit tools (@Test(expected = ...) or the @Rule ExpectedException JUnit rule feature).

但是這些方法并不那么優雅,并且不能很好地與其他工具可讀性混合.此外,JUnit 工具確實存在一些缺陷.

But these ways are not so elegant and don't mix well readability wise with other tools. Moreover, JUnit tooling does have some pitfalls.

  1. try-catch 塊,您必須圍繞測試的行為編寫塊并在 catch 塊中寫入斷言,這可能很好,但很多發現這種風格打斷了測試的閱讀流程.此外,您需要在 try 塊的末尾編寫一個 Assert.fail.否則,測試可能會錯過斷言的一側;PMD、findbugsSonar 會發現此類問題.

  1. The try-catch block you have to write the block around the tested behavior and write the assertion in the catch block, that may be fine but many find that this style interrupts the reading flow of a test. Also, you need to write an Assert.fail at the end of the try block. Otherwise, the test may miss one side of the assertions; PMD, findbugs or Sonar will spot such issues.

@Test(expected = ...) 功能很有趣,因為您可以編寫更少的代碼,然后編寫此測試據說不太容易出現編碼錯誤.但是這種方法在某些領域是缺乏的.

The @Test(expected = ...) feature is interesting as you can write less code and then writing this test is supposedly less prone to coding errors. But this approach is lacking in some areas.

  • 如果測試需要檢查異常的其他內容,例如原因或消息(好的異常消息非常重要,僅擁有精確的異常類型可能還不夠).
  • 同樣由于期望被放置在方法中,根據測試代碼的編寫方式,測試代碼的錯誤部分可能會引發異常,導致誤報測試,我不確定PMD、findbugsSonar 將對此類代碼提供提示.

  • If the test needs to check additional things on the exception like the cause or the message (good exception messages are really important, having a precise exception type may not be enough).
  • Also as the expectation is placed around in the method, depending on how the tested code is written then the wrong part of the test code can throw the exception, leading to false-positive test and I'm not sure that PMD, findbugs or Sonar will give hints on such code.

@Test(expected = WantedException.class)
public void call2_should_throw_a_WantedException__not_call1() {
    // init tested
    tested.call1(); // may throw a WantedException

    // call to be actually tested
    tested.call2(); // the call that is supposed to raise an exception
}

ExpectedException 規則也是嘗試修復之前的警告,但使用起來感覺有點別扭,因為它使用了期望樣式,EasyMock 用戶非常了解這種風格.這對某些人來說可能很方便,但如果您遵循 行為驅動開發 (BDD) 或 安排行為斷言 (AAA) 原則,則 ExpectedException 規則獲勝不適合那些寫作風格.除此之外,它可能會遇到與 @Test 方式相同的問題,具體取決于您將期望放在哪里.

The ExpectedException rule is also an attempt to fix the previous caveats, but it feels a bit awkward to use as it uses an expectation style, EasyMock users know very well this style. It might be convenient for some, but if you follow Behaviour Driven Development (BDD) or Arrange Act Assert (AAA) principles the ExpectedException rule won't fit in those writing style. Aside from that it may suffer from the same issue as the @Test way, depending on where you place the expectation.

@Rule ExpectedException thrown = ExpectedException.none()

@Test
public void call2_should_throw_a_WantedException__not_call1() {
    // expectations
    thrown.expect(WantedException.class);
    thrown.expectMessage("boom");

    // init tested
    tested.call1(); // may throw a WantedException

    // call to be actually tested
    tested.call2(); // the call that is supposed to raise an exception
}

即使預期的異常放在測試語句之前,如果測試遵循 BDD 或 AAA,它也會破壞您的閱讀流程.

Even the expected exception is placed before the test statement, it breaks your reading flow if the tests follow BDD or AAA.

另外,請參閱關于 JUnit 的 comment 問題ExpectedException 的作者.JUnit 4.13-beta-2 甚至棄用了這種機制:

Also, see this comment issue on JUnit of the author of ExpectedException. JUnit 4.13-beta-2 even deprecates this mechanism:

拉取請求 #1519:棄用 ExpectedException

Pull request #1519: Deprecate ExpectedException

方法 Assert.assertThrows 提供了一種更好的方法來驗證異常.此外,ExpectedException 的使用在與 TestWatcher 等其他規則一起使用時容易出錯,因為在這種情況下規則的順序很重要.

The method Assert.assertThrows provides a nicer way for verifying exceptions. In addition, the use of ExpectedException is error-prone when used with other rules like TestWatcher because the order of rules is important in that case.

因此,上述這些選項有很多注意事項,并且顯然無法避免編碼錯誤.

So these above options have all their load of caveats, and clearly not immune to coder errors.

  1. 在創建這個看起來很有希望的答案后,我意識到了一個項目,它是 catch-exception.

正如該項目的描述所說,它讓編碼人員編寫流暢的代碼行來捕獲異常,并為后面的斷言提供這個異常.您可以使用任何斷言庫,例如 Hamcrest 或 AssertJ.

As the description of the project says, it let a coder write in a fluent line of code catching the exception and offer this exception for the latter assertion. And you can use any assertion library like Hamcrest or AssertJ.

取自主頁的快速示例:

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
when(myList).get(1);

// then: we expect an IndexOutOfBoundsException
then(caughtException())
        .isInstanceOf(IndexOutOfBoundsException.class)
        .hasMessage("Index: 1, Size: 0") 
        .hasNoCause();

如您所見,代碼非常簡單,您在特定行捕獲異常,then API 是一個別名,將使用 AssertJ API(類似于使用 assertThat(ex).hasNoCause()...).在某些時候,該項目依賴于 AssertJ 的祖先 FEST-Assert.看來該項目正在醞釀對 Java 8 Lambdas 的支持.

As you can see the code is really straightforward, you catch the exception on a specific line, the then API is an alias that will use AssertJ APIs (similar to using assertThat(ex).hasNoCause()...). At some point the project relied on FEST-Assert the ancestor of AssertJ. It seems the project is brewing a Java 8 Lambdas support.

目前,這個庫有兩個缺點:

Currently, this library has two shortcomings :

  • 在撰寫本文時,值得注意的是,該庫基于 Mockito 1.x,因為它在后臺創建了測試對象的模擬.由于 Mockito 仍未更新 此庫不能與最終類或最終方法一起使用.即使它基于當前版本的 Mockito 2,這也需要聲明一個全局模擬制造商 (inline-mock-maker),這可能不是你想要的,作為這個模擬制造商與普通的模擬制造商有不同的缺點.

  • At the time of this writing, it is noteworthy to say this library is based on Mockito 1.x as it creates a mock of the tested object behind the scene. As Mockito is still not updated this library cannot work with final classes or final methods. And even if it was based on Mockito 2 in the current version, this would require to declare a global mock maker (inline-mock-maker), something that may not what you want, as this mock maker has different drawbacks that the regular mock maker.

它需要另一個測試依賴項.

It requires yet another test dependency.

一旦庫支持 lambda,這些問題將不適用.但是,AssertJ 工具集將復制該功能.

These issues won't apply once the library supports lambdas. However, the functionality will be duplicated by the AssertJ toolset.

綜合考慮如果不想使用catch-exception工具,我會推薦try-catch這個老好辦法塊,至少到JDK7.對于 JDK 8 用戶,您可能更喜歡使用 AssertJ,因為它提供的可能不僅僅是斷言異常.

Taking all into account if you don't want to use the catch-exception tool, I will recommend the old good way of the try-catch block, at least up to the JDK7. And for JDK 8 users you might prefer to use AssertJ as it offers may more than just asserting exceptions.

在 JDK8 中,lambda 進入了測試場景,事實證明它們是斷言異常行為的一種有趣方式.AssertJ 已更新,提供了一個很好的流暢 API 來斷言異常行為.

With the JDK8, lambdas enter the test scene, and they have proved to be an interesting way to assert exceptional behaviour. AssertJ has been updated to provide a nice fluent API to assert exceptional behaviour.

還有一個帶有 AssertJ 的示例測試:

And a sample test with AssertJ :

@Test
public void test_exception_approach_1() {
    ...
    assertThatExceptionOfType(IOException.class)
            .isThrownBy(() -> someBadIOOperation())
            .withMessage("boom!"); 
}

@Test
public void test_exception_approach_2() {
    ...
    assertThatThrownBy(() -> someBadIOOperation())
            .isInstanceOf(Exception.class)
            .hasMessageContaining("boom");
}

@Test
public void test_exception_approach_3() {
    ...
    // when
    Throwable thrown = catchThrowable(() -> someBadIOOperation());

    // then
    assertThat(thrown).isInstanceOf(Exception.class)
                      .hasMessageContaining("boom");
}

  • 隨著對 JUnit 5 的近乎完整的重寫,斷言已經 改進了 一點,它們可能被證明是一種有趣的開箱即用的方式來正確斷言異常.但實際上斷言 API 還是有點差,除了 assertThrows.

  • With a near-complete rewrite of JUnit 5, assertions have been improved a bit, they may prove interesting as an out of the box way to assert properly exception. But really the assertion API is still a bit poor, there's nothing outside assertThrows.

    @Test
    @DisplayName("throws EmptyStackException when peeked")
    void throwsExceptionWhenPeeked() {
        Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
    
        Assertions.assertEquals("...", t.getMessage());
    }
    

    您注意到 assertEquals 仍然返回 void,因此不允許像 AssertJ 這樣的鏈接斷言.

    As you noticed assertEquals is still returning void, and as such doesn't allow chaining assertions like AssertJ.

    此外,如果您記得與 MatcherAssert 的名稱沖突,請準備好與 Assertions 遇到相同的沖突.

    Also if you remember name clash with Matcher or Assert, be prepared to meet the same clash with Assertions.

    我想總結一下,今天 (2017-03-03) AssertJ 的易用性、可發現的 API、快速的開發速度以及 事實上的em> 測試依賴是 JDK8 的最佳解決方案,不管測試框架(JUnit 與否),之前的 JDK 應該依賴 try-catch 塊,即使他們覺得笨重.

    I'd like to conclude that today (2017-03-03) AssertJ's ease of use, discoverable API, the rapid pace of development and as a de facto test dependency is the best solution with JDK8 regardless of the test framework (JUnit or not), prior JDKs should instead rely on try-catch blocks even if they feel clunky.

    這篇關于如何驗證沒有拋出異常的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

    【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!
  • 相關文檔推薦

    How to mock super reference (on super class)?(如何模擬超級參考(在超級類上)?)
    Java mock database connection(Java 模擬數據庫連接)
    Mockito ClassCastException - A mock cannot be cast(Mockito ClassCastException - 無法投射模擬)
    Set value to mocked object but get null(將值設置為模擬對象但獲取 null)
    How to mock DriverManager.getConnection(...)?(如何模擬 DriverManager.getConnection(...)?)
    Mockito; verify method was called with list, ignore order of elements in list(模擬;使用列表調用驗證方法,忽略列表中元素的順序)
    主站蜘蛛池模板: 成人在线观看免费 | 欧美操操操| 日韩视频―中文字幕 | 日韩无 | 91精品久久久久久久久久入口 | 九九热精品在线视频 | 精品欧美一区二区在线观看 | 国产精品观看 | 欧美成人精品二区三区99精品 | 另类专区亚洲 | 日韩在线观看 | 午夜码电影 | 国产精品成人在线播放 | 福利一区视频 | www.精品国产| 毛片免费观看 | 国产精品99久久久久久www | 欧美日韩久 | 狠狠色狠狠色综合系列 | 国产十日韩十欧美 | 在线观看成人 | 中文在线一区二区 | 日韩高清三区 | 波多野结衣中文字幕一区二区三区 | 国产欧美精品一区二区色综合朱莉 | 91视频网 | 免费日韩av网站 | 国产精品久久免费观看 | 成人在线视频看看 | 久久一级| 久久精品国产一区二区电影 | 欧美一区二区三区在线看 | av在线播放网址 | 久久国产精品偷 | 欧美成视频 | 亚洲免费一| 丁香五月网久久综合 | 成人影| 亚洲高清视频一区二区 | 成人久久久 | www.日韩系列 |