有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

异常处理Java TestNG:为什么我的断言在trycatch块中写入时总是通过

我尝试使用一个简单的代码,使用org.testng.Assert断言2个用例。在第一个用例中,我断言了两个不相等的值,它们Fail是正确的

但是在第二个用例中,当我在try-catch块中断言两个不相等的值时,结果总是作为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()中,虽然断言失败了,但为什么执行不是从这个Test出来的呢
  2. 在test2()中,try块似乎失败了,因此执行到达catch块,并且Exception Occurred被打印出来。为什么在执行断言代码时try块会在这里失败

共 (4) 个答案

  1. # 1 楼答案

    你的第二个案例充满了问题,这就是为什么它表现得如此奇怪。查看由数字标记的行:

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

    1-“assert*”方法调用不应被try-catch块包装。它们被设计用来检查数据,并通过抛出错误(!)来处理数据的无效性

    2-你正在尝试捕捉所有可以在try部分抛出的内容。在常见情况下,应用程序的业务逻辑使用异常,而不是错误。异常表明出现了一些问题,您可以从中恢复。错误主要表明出现了一些严重的问题,如(硬盘故障等),您只需在应用程序停止之前处理应用程序的数据。异常和错误是从Throwable继承的。”assert*'方法设计为抛出特定于“catch”块捕获的错误

    3-如果你不处理捕获到的异常,你就是在忽略它。这就是为什么你的方法总是成功的

    要更正第二次测试,您可以: a) 从方法体中删除try-catch节 b) 将“t”参数的类型从Throwable更改为Exception c) 在“catch”块末尾添加“throw t”

  2. # 2 楼答案

    如果您查看assertEquals方法的源代码,您将看到它可以归结为fail方法(就像许多其他断言一样)

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

    正如我们所看到的,它抛出AssertionError,您正在catch(Throwable t)中捕获它。因此,JUnit无法判断测试是否失败,从而宣布它通过了测试

    如果捕获异常是测试的一部分(您预期会发生异常),我建议您查看JUnit文档:Exception testing

  3. # 3 楼答案

    后来在理解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将使该方法失败
    请注意,例如printStackTrace();也不会让你的测试失败

  4. # 4 楼答案

    如果您浏览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
    }
    

    第三部分:

    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 + ">";
    }
    

    因此,您已收到第3部分的返回消息

    java.lang.AssertionError: expected [20] but found [12]

    要全面了解异常JUnit规则,请通过following tutorial

    预期异常JUnit规则

    要断言JUnit引发了异常,通常使用try/fail/catch习惯用法或@Test注释的预期元素。尽管比前者更简洁,但有一种观点认为使用expected并不支持您可能要测试的所有情况。示例是在异常后执行附加测试或针对实际异常消息进行测试

    JUnit4.7引入了next progression,这是一条@规则,它提供了两个世界中最好的东西。本文权衡了每种方法的优缺点,并仔细研究了每种方法的语法。 try/fail/catch成语

    典型的模式是捕获异常,如果从未抛出,则显式失败

    @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)
        ...
    

    该习惯用法的潜在优势在于,它提供了针对实际异常进行断言的机会,以及在预期之后执行额外工作的机会。除了噪音之外,主要的缺点是很容易忘记包含失败调用。如果真的先做测试,我们总是以红色运行测试,这不会是一个问题,但很多时候事情都会漏网之鱼。在实践中,我已经看到了太多的例子,其中一个遗漏的失败给出了误报

    @测试(预期=异常.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
    

    资源链接:What exactly does assertEquals check for when asserting lists?