简体   繁体   English

Java - TestNG:为什么我的Assertion总是在try-catch块中写入时通过

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

I was trying with a simple code using org.testng.Assert to assert 2 use-cases. 我正在尝试使用org.testng.Assert的简单代码来断言2个用例。 In the first use-case I am asserting 2 unequal values which Fail correctly. 在第一个用例中,我声明了2个不正确的值,它们正确地Fail

But in the second use-case when I am asserting 2 unequal values within the try-catch block, the result is always returned as Pass 但是在第二个用例中,当我在try-catch块中断言2个不相等的值时,结果总是作为Pass返回

My code is as follows: 我的代码如下:

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

The result I am getting is: 我得到的结果是:

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)

My question are: 我的问题是:

  1. In test2() though the Assertion is failing why doesn't the execution comes out of this Test ? 在test2()中虽然Assertion失败了,为什么执行不会出现在这个Test
  2. In test2() it seems try block is failing, so the execution reaches catch block and Exception Occurred gets printed. 在test2()中,似乎try块失败,因此执行到达catch块并且Exception Occurred被打印。 Why should try block fail here when the assertion code is getting executed? 当断言代码执行时,为什么try阻塞失败呢?

If you look at the source code of assertEquals method, you'll see that it all boils down to fail method (as do many other asserts). 如果你看一下assertEquals方法的源代码,你会发现它都归结为fail方法(和许多其他的断言一样)。

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

As we can see, it throws AssertionError , which you are catching in catch(Throwable t) . 正如我们所看到的,它会抛出AssertionError ,你在catch(Throwable t)catch(Throwable t) So JUnit has no way of telling that the test has failed , thus declaring it passed. 所以JUnit无法告诉测试失败 ,因此声明它已通过。

If catching an exception is part of your test (you are expecting an exception), I suggest you have a look at JUnit documentation: Exception testing 如果捕获异常是测试的一部分(您期望异常),我建议您查看JUnit文档: 异常测试

If you go through the source code of junit4, https://github.com/junit-team/junit4/blob/master/src/main/java/junit/framework/Assert.java#L71 如果你查看junit4的源代码,请访问https://github.com/junit-team/junit4/blob/master/src/main/java/junit/framework/Assert.java#L71

You will get why the test1 is failing 你会明白test1失败的原因

Part#1: 第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
}

Part#2: 第2部分:

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

Part#3: 第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 + ">";
}

So you have gotten Part#3's return message as 所以你得到了Part#3的回复信息

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

For full phase understanding of Exceptions JUnit Rule, Go through the following tutorial : 有关异常JUnit规则的完整阶段理解,请完成以下教程

Expecting Exceptions JUnit Rule 期待JUnit规则的异常

To make an assertion that an exception was thrown with JUnit, it's fairly common to use the try/fail/catch idiom or the expected element of the @Test annotation. 为了断言使用JUnit抛出异常,使用try / fail / catch惯用法或@Test注释的期望元素是相当常见的。 Despite being more concise than the former, there is an argument that using expected doesn't support all the cases you may want to test. 尽管比前者更简洁,但有一种观点认为使用预期并不支持您可能想要测试的所有情况。 The example being to perform additional testing after the exception or testing against the actual exception message. 示例是在异常之后执行附加测试或针对实际异常消息进行测试。

JUnit 4.7 introduces the next progression, a @Rule that offers the best of both worlds. JUnit 4.7引入了下一个进程,一个提供两全其美的@Rule。 This articles weighs up the pros and cons of each approach and takes a closer look at the syntax of each. 本文重点介绍了每种方法的优缺点,并仔细研究了每种方法的语法。 The try/fail/catch Idiom 尝试/失败/捕获成语

The typical pattern is to catch an exception or fail explicitly if it was never thrown. 典型的模式是捕获异常,如果从未抛出则显式失败。

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

which would highlight a failure in the following way. 这会以下列方式强调失败。

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

The idiom has potential advantages in that it offers the opportunity to assert against the actual exception as well as performing additional work after the expectation. 这个成语具有潜在的优势,因为它提供了对实际例外进行断言以及在期望之后执行额外工作的机会。 Aside from the noise, the major drawback however is that its very easy to forget to include the fail call. 除了噪音之外,主要的缺点是它很容易忘记包括失败呼叫。 If genuinely doing test first, where we always run the test red, this wouldn't be a problem but all too often things slip through the net. 如果真的首先进行测试,我们总是在测试中运行红色,这不会是一个问题,但是经常会出现问题。 In practice, I've seen far too many examples with a missing fail giving false positives. 在实践中,我看到太多的例子,失败的失败给出了误报。

@Test (expected = Exception.class) @Test(expected = Exception.class)

Using the expected element, we can rewrite the test as follows. 使用期望的元素,我们可以如下重写测试。

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

which will result in the following failure. 这将导致以下失败。

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

Resource Link: What exactly does assertEquals check for when asserting lists? 资源链接: 断言列表时assertEquals究竟检查了什么?

Your second case is full of problems, that is why it behave so strange. 你的第二个案例充满了问题,这就是为什么它表现得如此奇怪。 Look at lines marked by numbers: 查看以数字标记的行:

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

1 - 'assert*' methods invocations should not be wrapped by try-catch block. 1 - 'assert *'方法调用不应该被try-catch块包装。 They are designed to check data and handle it's invalidness by throwing Errors (!). 它们旨在通过抛出错误(!)来检查数据并处理它的无效性。

2 - You are trying to catch everything can be thrown in try section. 2 - 你试图抓住一切可以在试试部分抛出。 Business logic of applications in common cases uses Exceptions, not Errors. 常见情况下应用程序的业务逻辑使用异常,而不是错误。 Exceptions show that some problem appeared from which you can recover. 例外情况表明出现了一些可以恢复的问题。 Errors mostly show that some serious problem like (hard disc failure and so on) appeared and you just need to handle application's data before the app will be stopped. 错误主要表现出一些严重的问题,如(硬盘故障等),你只需要在应用程序停止之前处理应用程序的数据。 Exception and Error are inherit from Throwable. 异常和错误是从Throwable继承的。 'assert*' methods designed that way to throw Errors specifically not to be caught by 'catch' blocks. 'assert *'方法设计的方式是抛出错误,特别是不被'catch'块捕获。

3 - By not doing with caught exception you are just ignoring it. 3 - 通过不处理捕获的异常,你只是忽略它。 That's why your method always will be finished with success. 这就是为什么你的方法总是会成功完成的原因。

To correct second test you can: a) remove try-catch section from the method's body b) change 't' parameter's type from Throwable to Exception c) add 'throw t' at the end of 'catch' block 要纠正第二次测试,您可以:a)从方法体中删除try-catch部分b)将't'参数的类型从Throwable更改为Exception c)在'catch'块的末尾添加'throw t'

I too had faced the similar problem, later on when understanding Java, that, when the calling method wants to know about the exception in its called method, called method should contain 'throw exception;' 我也遇到过类似的问题,后来在理解Java的时候,当调用方法想知道它的被调用方法中的异常时,被调用的方法应该包含'throw exception;' statement in its Catch block. Catch块中的语句。

In this way, 通过这种方式,

@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 will come to know that, there is an exception thrown. TestNG会知道,抛出异常。 Then, TestNG will fail that method. 然后,TestNG将失败该方法。
Please note, e.printStackTrace(); 请注意,e.printStackTrace(); also wont Fail your Test case. 也不会失败你的测试用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM