簡體   English   中英

Java - TestNG:為什么我的Assertion總是在try-catch塊中寫入時通過

[英]Java - TestNG : Why does my Assertion always passes when written within try-catch block

我正在嘗試使用org.testng.Assert的簡單代碼來斷言2個用例。 在第一個用例中,我聲明了2個不正確的值,它們正確地Fail

但是在第二個用例中,當我在try-catch塊中斷言2個不相等的值時,結果總是作為Pass返回

我的代碼如下:

package demo;
import org.testng.Assert;
import org.testng.annotations.Test;
public class Q43710035 
{

    @Test
    public void test1() 
    {
        System.out.println("Within test1");
        int a = 12;
        int b =20;
        Assert.assertEquals(a, b);

    }

    @Test
    public void test2() 
    {
        System.out.println("Within test2");
        int a = 12;
        int b =20;

        try 
        {
            Assert.assertEquals(a, b);
        }catch(Throwable t)
        {
            System.out.println("Exception Occurred");
        }
    }
}

我得到的結果是:

Within test1
Within test2
Exception Occurred
PASSED: test2
FAILED: test1
java.lang.AssertionError: expected [20] but found [12]
at org.testng.Assert.fail(Assert.java:94)

我的問題是:

  1. 在test2()中雖然Assertion失敗了,為什么執行不會出現在這個Test
  2. 在test2()中,似乎try塊失敗,因此執行到達catch塊並且Exception Occurred被打印。 當斷言代碼執行時,為什么try阻塞失敗呢?

如果你看一下assertEquals方法的源代碼,你會發現它都歸結為fail方法(和許多其他的斷言一樣)。

public static void fail(String message) {
    if(message == null) {
        throw new AssertionError();
    } else {
        throw new AssertionError(message);
    }
}

正如我們所看到的,它會拋出AssertionError ,你在catch(Throwable t)catch(Throwable t) 所以JUnit無法告訴測試失敗 ,因此聲明它已通過。

如果捕獲異常是測試的一部分(您期望異常),我建議您查看JUnit文檔: 異常測試

如果你查看junit4的源代碼,請訪問https://github.com/junit-team/junit4/blob/master/src/main/java/junit/framework/Assert.java#L71

你會明白test1失敗的原因

第1部分:

 /** * Asserts that two objects are equal. If they are not * an AssertionFailedError is thrown with the given message. */ 
static public void assertEquals(String message, Object expected, Object actual) {
    if (expected == null && actual == null) {
        return;
    }
    if (expected != null && expected.equals(actual)) {
        return;
    }
    failNotEquals(message, expected, actual); //It calls Part#2
}

第2部分:

static public void failNotEquals(String message, Object expected, Object actual) {
    fail(format(message, expected, actual)); //It calls Part#3 format(...) method
}

第3:

public static String format(String message, Object expected, Object actual) {
    String formatted = "";
    if (message != null && message.length() > 0) {
        formatted = message + " ";
    }
    return formatted + "expected:<" + expected + "> but was:<" + actual + ">";
}

所以你得到了Part#3的回復信息

java.lang.AssertionError:expected [20]但發現[12]

有關異常JUnit規則的完整階段理解,請完成以下教程

期待JUnit規則的異常

為了斷言使用JUnit拋出異常,使用try / fail / catch慣用法或@Test注釋的期望元素是相當常見的。 盡管比前者更簡潔,但有一種觀點認為使用預期並不支持您可能想要測試的所有情況。 示例是在異常之后執行附加測試或針對實際異常消息進行測試。

JUnit 4.7引入了下一個進程,一個提供兩全其美的@Rule。 本文重點介紹了每種方法的優缺點,並仔細研究了每種方法的語法。 嘗試/失敗/捕獲成語

典型的模式是捕獲異常,如果從未拋出則顯式失敗。

@Test
public void example1() {
    try {
        find("something");
        fail();
    } catch (NotFoundException e) {
        assertThat(e.getMessage(), containsString("could not find something"));
    }
    // ... could have more assertions here
}

這會以下列方式強調失敗。

java.lang.AssertionError: expected an exception
    at org.junit.Assert.fail(Assert.java:91)
    at bad.roboot.example.ExceptionTest.example1(ExceptionTest.java:20)
    ...

這個成語具有潛在的優勢,因為它提供了對實際例外進行斷言以及在期望之后執行額外工作的機會。 除了噪音之外,主要的缺點是它很容易忘記包括失敗呼叫。 如果真的首先進行測試,我們總是在測試中運行紅色,這不會是一個問題,但是經常會出現問題。 在實踐中,我看到太多的例子,失敗的失敗給出了誤報。

@Test(expected = Exception.class)

使用期望的元素,我們可以如下重寫測試。

@Test (expected = NotFoundException.class)
public void example2() throws NotFoundException {
    find("something");
    // ... this line will never be reached when the test is passing
}

這將導致以下失敗。

java.lang.AssertionError: Expected exception: bad.robot.example.NotFoundException

資源鏈接: 斷言列表時assertEquals究竟檢查了什么?

你的第二個案例充滿了問題,這就是為什么它表現得如此奇怪。 查看以數字標記的行:

    try 
    {
        Assert.assertEquals(a, b); // 1
    }catch(Throwable t) // 2
    {
        System.out.println("Exception Occurred"); // 3
    }

1 - 'assert *'方法調用不應該被try-catch塊包裝。 它們旨在通過拋出錯誤(!)來檢查數據並處理它的無效性。

2 - 你試圖抓住一切可以在試試部分拋出。 常見情況下應用程序的業務邏輯使用異常,而不是錯誤。 例外情況表明出現了一些可以恢復的問題。 錯誤主要表現出一些嚴重的問題,如(硬盤故障等),你只需要在應用程序停止之前處理應用程序的數據。 異常和錯誤是從Throwable繼承的。 'assert *'方法設計的方式是拋出錯誤,特別是不被'catch'塊捕獲。

3 - 通過不處理捕獲的異常,你只是忽略它。 這就是為什么你的方法總是會成功完成的原因。

要糾正第二次測試,您可以:a)從方法體中刪除try-catch部分b)將't'參數的類型從Throwable更改為Exception c)在'catch'塊的末尾添加'throw t'

我也遇到過類似的問題,后來在理解Java的時候,當調用方法想知道它的被調用方法中的異常時,被調用的方法應該包含'throw exception;' Catch塊中的語句。

通過這種方式,

@Test
public void test2() 
{
    System.out.println("Within test2");
    int a = 12;
    int b =20;

    try 
    {
        Assert.assertEquals(a, b);
    }catch(Exception e)
    {
        System.out.println("Exception Occurred");
        throw e;
    }
}

TestNG會知道,拋出異常。 然后,TestNG將失敗該方法。
請注意,e.printStackTrace(); 也不會失敗你的測試用例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM