How JUnit 4 correctly tests exceptions

Source: Internet
Author: User

This article describes how to properly test exceptions under JUnit 4, and I'll start with the try. Catch the way to talk about, and then to @Test (Expected=exception.class), and finally on the @Rules public expectedexception implementation, the final basic can be determined with @Rules is the most convenient.

When we use JUnit to test the exception, the easiest way is to use Try...catch to catch the exception, we need to assert the following conditions:

1. Exceptions that do throw
2. Class type that throws an exception
3. The specific type of exception that is thrown, general check for the assertion of the string contained in the message property of the exception

So the usual code you might write:

@Test  Public void passwordlengthlessthan6lettersthrowsexception () {    try{        password.validate (" 123 ");        Fail ("No exception thrown." );    } Catch (Exception ex) {        instanceof  invalidpasswordexception);        Asserttrue (Ex.getmessage (). Contains ("contains at least 6"));}    }

The method to be tested here is whether the Password.validate () method throws the corresponding exception, and note that there are no missing try

Fail ("No Exception thrown.")

Line of code, or if the method being tested does not throw an exception, the use case is passed, and you expect to throw an exception.

The above soil method is suitable for which version of JUnit, but we have already stepped into JUnit 4, it is not necessary to test the method exception. Although this can also determine whether to perform the expected exception, but it still has drawbacks, and then a comparison will know, Try...catch method, JUnit can not give you a detailed assertion failure reason.

So what can I do to test for exceptions since JUnit 4? Use the @Test (execpted=exception.class) annotation on the line, and refer to the following code:

@Test (expected = nullpointerexception.  Class)publicvoidthrows  invalidpasswordexception {    Password.validate (null);}

If the method being tested has a nullpointerexception type that is the assertion succeeds, the @Test (expected = Nullpointerexception.class) can only determine the type of the exception, There is no corresponding annotation to assert the more specific information of the exception, that is, the message property that throws the exception cannot be determined.

Well, sometimes we throw one type of exception in a method several times, but the reason is different, that is, the message information of the exception is different, for example, there are two kinds of exceptions when the invalidpasswordexception occurs:

New Invalidpasswordexception ("Password must contains at least 6 letters.")
New Invalidpasswordexception ("Password length less than letters")

There is a way to assert the exception of the message, for this, since JUnit 4.7 has given us a more perfect choice, is the following code:

@Rule  Public ExpectedException Expectedex = expectedexception.none (); @Testpublicvoidthrows invalidpasswordexception {    expectedex.expect (invalidpassrdexception. class );    Expectedex.expectmessage ("required");    Password.validate ("");}

The above code should focus on several:

1. The expectedexception variable declaration of the @Rule annotation, which must be public
2. @Test, can not be written as @Test (Expected=invalidpasswordexception.class), or not properly tested, that is,
The Expectedex.expectxxx () method in the @Test (Expected=invalidpasswordexception.class) and test methods cannot coexist simultaneously
3. The argument in Expectedex.expectmessage () is Matcher or subString, which means that a regular expression can be used to determine whether or not to include a substring
4. Then there is a very heavy, the test method is written in the Expectedex.expectxxx () method, or else can not correctly test the exception
5. The last one is, as long as the test method directly throws the exception of the method being tested, it does not affect the exception you care about

The previous approach to using Try...catch to correctly test anomalies, @Test (expected= ...) or @Rule and the Try...catch method of comparison, it is clear that the method recommended by JUnit 4 is straightforward. And what does JUnit suggest to you when the test fails?

 

Try...catch the prompt when the test exception fails:

When there is no exception:

Java.lang.AssertionError:No exception thrown.
At Org.junit.Assert.fail (assert.java:91)
At Cc.unmi.PasswordTest.passwordLengthLessThan6LettersThrowsException (passwordtest.java:20)

When the exception type is incorrect or the message of the exception is incorrect:

Java.lang.AssertionError:
At Org.junit.Assert.fail (assert.java:91)
At Org.junit.Assert.assertTrue (assert.java:43)
At Org.junit.Assert.assertTrue (assert.java:54)
At Cc.unmi.PasswordTest.passwordLengthLessThan6LettersThrowsException (passwordtest.java:22)

It's not particularly big to help us with the wrong positioning.

See @Test (Expected=invalidpasswordexception.class) when the test fails the prompt:

Java.lang.AssertionError:Expected exception:cc.unmi.InvalidPasswordException
At Org.junit.internal.runners.statements.ExpectException.evaluate (expectexception.java:32)
At Org.junit.rules.expectedexception$expectedexceptionstatement.evaluate (expectedexception.java:110)

To test the exception with @Rules ExpectedException method, the prompt when it fails:

Java.lang.AssertionError:
Expected: (Exception with message a string containing "YES. Required "and an instance of Java.lang.NullPointerException)
Got: <cc.unmi.invalidpasswordexception:password is required.>

At Org.junit.Assert.assertThat (assert.java:778)
At Org.junit.Assert.assertThat (assert.java:736)
At Org.junit.rules.expectedexception$expectedexceptionstatement.evaluate (expectedexception.java:114)

Especially when @Rules ExpectedException method, why test failure hints clearly. What exception is expected, what string is contained in the exception message, what type of exception is actually obtained, and what is the message in the exception. With this, you know how to fix your program as soon as you see it.

So here we really have no reason to @Test (expected= ...) or @Rule expectedexception.

How JUnit 4 correctly tests exceptions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.