Java - TestNG: Why is my statement always passed when it is written to the try-catch block

I tried using simple code to use org.testng.Assert to approve 2 use cases. In the first case, I affirm 2 unequal values ​​that Fail correctly.

But in the second use case, when I assert 2 unequal values ​​in the try-catch block, the result always returns as 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"); } } } 

As a result, I get:

 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 is:

  • In test2 (), although the statement does not work, why does this Test fail?
  • In test2 (), it seems that the try block is not working, so execution reaches the catch block and an Exception Occurred is printed. Why is try blocked here when the verification code runs?
+8
java exception-handling assertions try-catch testng
source share
4 answers

If you are viewing the source code for junit4, https://github.com/junit-team/junit4/blob/master/src/main/java/junit/framework/Assert.java#L71

You will get why test1 is not working

Part 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:

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

Part # 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 received a message about the return of part number 3 as

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

For a full-sized understanding of exceptions. JUnit rule. Go through the tutorial :

Waiting for Exceptions JUnit Rule

To make the claim that an exception was thrown using JUnit, it is common to use the try / fail / catch iteration or the expected @Test annotation element. Although it was shorter than the previous one, there is an argument that using the expected does not support all cases that you can test. An example is performing additional testing after an exception or testing against the actual exception message.

JUnit 4.7 introduces the next progression, @Rule, which offers the best of both worlds. These articles weigh the pros and cons of each approach and examine in more detail the syntax of each. Idiom try / fail / catch

A typical pattern is to catch an exception or fail clearly if it has never been 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 the error as follows.

 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 makes it possible to argue against the actual exclusion, as well as perform additional work after waiting. Besides the noise, the main disadvantage is that it is very easy to forget to turn on the call of failure. To be honest, do the test first, where we always run the red test, this will not be a problem, but too often things slip through the network. In practice, I have seen too many examples with a missing failure giving false positives.

@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 lead to the next failure.

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

Resource Link: What exactly does assertEquals check when approving lists?

+3
source share

If you look at the source code of the assertEquals method, you will see that it all boils down to the fail method (like many other statements).

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

As we can see, it throws an AssertionError that you catch in catch(Throwable t) . So, JUnit cannot say that the test failed , thereby announcing that it passed.

If catching an exception is part of your test (you are expecting an exception), I suggest you check out the JUnit documentation: Exclusive Testing

+11
source share

Your second case is full of problems, so it behaves so strangely. Look at the lines marked with numbers:

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

1 - 'assert *' method calls should not be wrapped with a try-catch block. They are designed to verify data and eliminate invalidation, causing errors (!).

2 - You are trying to catch everything that can be thrown in the try section. In business logic, applications typically use exceptions rather than errors. Exceptions show that there is some kind of problem from which you can recover. Errors basically show that some serious problems have occurred, such as (hard drive failure, etc.), and you just need to process the application data before the application is stopped. Exception and error inherit from Throwable. 'assert *' methods designed to eliminate errors so as not to be caught by catch blocks.

3 - Without making a caught exception, you simply ignore it. That is why your method will always be completed with success.

To fix the second test, you can: a) remove the try-catch section from the method body b) change the parameter type 't' from Throwable to Exception c) add 'throw t' to the end of the catch block

+2
source share

I also encountered a similar problem, and later, when I realized that when the calling method wants to know about the exception in its called method, the called method should contain a "throw exception"; in the catch block.

Thus,

 @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 finds out that there is an exception. Then TestNG will not be able to execute this method.
Please note: e.printStackTrace (); also fail to verify your test case.

+1
source share

All Articles