Sometimes we want to test our methods for exceptions. TestNG allows us to perform exceptions testing using expectedExceptions
and expectedExceptionsMessageRegExp
parameters of @Test
annotation.
TestNG expectedExceptions
Let’s say we have a simple utility method for dividing two numbers.
1 2 3 4 5 6 7 8 |
package com.journaldev.exceptions; public class MathUtils { public int divide(int x, int y) { return x / y; } } |
We know that if we try to divide a number by 0, it will throw java.lang.ArithmeticException
with message as / by zero
.
Let’s write a TestNG Test class to test this exception scenario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.journaldev.exceptions; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import org.testng.annotations.DataProvider; public class MathUtilsTest { @Test(dataProvider = "dp", expectedExceptions = {ArithmeticException.class }) public void f(Integer x, Integer y) { MathUtils mu = new MathUtils(); assertEquals(mu.divide(x, y), x / y); } @DataProvider public Object[][] dp() { return new Object[][] { new Object[] { 4, 0 } }; } } |
We get the following output when we execute above test class.
1 2 3 4 |
[RemoteTestNG] detected TestNG version 6.14.3 PASSED: f(4, 0) |
If we remove the expectedExceptions
attribute from the @Test
annotation, then our test case will fail with below message.
1 2 3 4 5 6 7 |
[RemoteTestNG] detected TestNG version 6.14.3 FAILED: f(4, 0) java.lang.ArithmeticException: / by zero at com.journaldev.exceptions.MathUtils.divide(MathUtils.java:6) at com.journaldev.exceptions.MathUtilsTest.f(MathUtilsTest.java:13) |
expectedExceptions
takes value as class array, so below value will work fine too.
1 2 3 |
expectedExceptions = {ArithmeticException.class, NullPointerException.class } |
TestNG Test expectedExceptionsMessageRegExp
We can extend our test method to look for exception message too. Test annotation expectedExceptionsMessageRegExp
uses regular expression. Let’s see few examples of how we can use it.
1 2 3 4 5 6 7 8 |
@Test(dataProvider = "dp", expectedExceptions= {ArithmeticException.class}, expectedExceptionsMessageRegExp="/ by zero") public void f(Integer x, Integer y) { MathUtils mu = new MathUtils(); assertEquals(mu.divide(x, y), x/y); } |
Above test method will pass only when ArithmeticException is thrown with the exact message as “/ by zero”.
1 2 3 4 |
[RemoteTestNG] detected TestNG version 6.14.3 PASSED: f(4, 0) |
Let’s change the message so that our test will fail.
1 2 3 4 5 6 7 8 |
@Test(dataProvider = "dp", expectedExceptions= {ArithmeticException.class}, expectedExceptionsMessageRegExp="by zero") public void f(Integer x, Integer y) { MathUtils mu = new MathUtils(); assertEquals(mu.divide(x, y), x/y); } |
Our test will fail with following console output.
1 2 3 4 5 6 7 |
<span style="color: #008000;"><strong><code> [RemoteTestNG] detected TestNG version 6.14.3 FAILED: f(4, 0) org.testng.TestException: The exception was thrown with the wrong message: expected "by zero" but got "/ by zero" at org.testng.internal.ExpectedExceptionsHolder.wrongException(ExpectedExceptionsHolder.java:71) </code></strong></span> |
Let’s see how we can use the regular exception when we are not sure of the exact message of exception.
1 2 3 4 5 6 7 8 |
@Test(dataProvider = "dp", expectedExceptions= {ArithmeticException.class}, expectedExceptionsMessageRegExp=".* by zero*.") public void f(Integer x, Integer y) { MathUtils mu = new MathUtils(); assertEquals(mu.divide(x, y), x/y); } |
This test will pass because the regex provided by us will match with the exception message being thrown.