Tests. Do I really need to add "throws Exception"? - java

I saw people using "throws Exception" in tests, but I never do. Should I worry? I never had any issues with that. What's the difference?
#Test()
public void test() throws Exception
{
//Do something
}
or
#Test()
public void test()
{
//Do something
}

If the code you are testing throws an exception, you must handle it in some way. Either by declaring a "throws Exception" in the method signature, or by using try-catch.
If the code you are calling in the method does not throw any exceptions, then you dont need either of those. The compiler will let you know if you need to catch an exception in some way.
Also note that you can do tests that makes sure an exception is thrown, see this answer

junit will mark a test as being in "error state" if an exception is thrown from that method. For most usecases, this is essentially the same as failing a test (in the sense that a test that completed in error state did not succeed). A lot of test authors don't like the hassle (or the code-uglification) associated with handling checked exceptions.
E.g., Consider a test that should run a couple of methods and assert the end state of an object:
public class SomeTest
SomeObject so;
#Before
public void setUp() {
so = new SomeObject();
}
#Test
public void TestSomeFlow() {
try {
so.init();
// must catch in order to avoid a compilation error
} catch (InitExceptionIDontCareAbout e) {
fail ("init failed");
}
try {
so.doSomething();
// must catch in order to avoid a compilation error
} catch (SomeOtherExceptionIDontCareAbout e) {
fail ("doSomething failed");
}
assertTrue ("doSomething didn't work", so.isSomethingDone());
}
}
Now consider how much cleaner the code looks without exception handling:
public class SomeTest
SomeObject so;
#Before
public void setUp() {
so = new SomeObject();
}
// Any exception throwm will mean the test did not succeed
#Test
public void TestSomeFlow() throws Exception {
so.init();
so.doSomething();
assertTrue ("doSomething didn't work", so.isSomethingDone());
}
}

Functionally, there is no difference. It only means that the compiler wont complain if you throw a non-RuntimeException. Since JUnit will catch any exception thrown by the test method anyway, it does not really matter.
However, it is usually considered a better practice to catch the Exception yourself and use the fail method of JUnit, in which case you do not need the throws clause.

Related

Java Eclipse - JUnit test expects exception but still fails when exception is [duplicate]

I wrote some test cases to test some method. But some methods throw an exception. Am I doing it correctly?
private void testNumber(String word, int number) {
try {
assertEquals(word, service.convert(number));
} catch (OutOfRangeNumberException e) {
Assert.fail("Test failed : " + e.getMessage());
}
}
#Test
public final void testZero() {
testNumber("zero", 0);
}
If I pass -45, it will fail with OutOfRangeException but I am not able to test specific exception like #Test(Expected...)
An unexpected exception is a test failure, so you neither need nor want to catch one.
#Test
public void canConvertStringsToDecimals() {
String str = "1.234";
Assert.assertEquals(1.234, service.convert(str), 1.0e-4);
}
Until service does not throw an IllegalArgumentException because str has a decimal point in it, that will be a simple test failure.
An expected exception should be handled by the optional expected argument of #Test.
#Test(expected=NullPointerException.class)
public void cannotConvertNulls() {
service.convert(null);
}
If the programmer was lazy and threw Exception, or if he had service return 0.0, the test will fail. Only an NPE will succeed. Note that subclasses of the expected exception also work. That's rare for NPEs, but common with IOExceptions and SQLExceptions.
In the rare case that you want to test for a specific exception message, you use the newish ExpectedException JUnit #Rule.
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void messageIncludesErrantTemperature() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("-400"); // Tests that the message contains -400.
temperatureGauge.setTemperature(-400);
}
Now, unless the setTemperature throws an IAE and the message contains the temperature the user was trying to set, the test fails. This rule can be used in more sophisticated ways.
Your example can best be handled by:
private void testNumber(String word, int number)
throws OutOfRangeNumberException {
assertEquals(word, service.convert(number));
}
#Test
public final void testZero()
throws OutOfRangeNumberException {
testNumber("zero", 0);
}
You can inline testNumber; now, it does not help much. You can turn this into a parametrized test class.
Remove the try-catch block and add throws Exception to your test method, like:
#Test
public final void testZero() throws Exception {
assertEquals("zero", service.convert(0));
}
JUnit expects failing tests will throw Exceptions, your catching them is just stopping JUnit from being able to report them properly. Also this way the expected property on the #Test annotation will work.
You don't need to catch the exception to fail the test. Just let it go (by declaring throws) and it will fail anyway.
Another case is when you actually expect the exception, then you put fail at the end of try block.
For example:
#Test
public void testInvalidNumber() {
try {
String dummy = service.convert(-1));
Assert.fail("Fail! Method was expected to throw an exception because negative numbers are not supported.")
} catch (OutOfRangeException e) {
// expected
}
}
You can use this kind of test to verify if your code is properly validating input and handles invalid input with a proper exception.
There are several strategies that are open to you to deal with expected exceptions in your tests. I think the JUnit annotations and try/catch idiom have already been mentioned above. I'd like to draw attention to the Java 8 option of Lambda expressions.
For instance given:
class DummyService {
public void someMethod() {
throw new RuntimeException("Runtime exception occurred");
}
public void someOtherMethod(boolean b) {
throw new RuntimeException("Runtime exception occurred",
new IllegalStateException("Illegal state"));
}
}
You can do this:
#Test
public void verifiesCauseType() {
// lambda expression
assertThrown(() -> new DummyService().someOtherMethod(true))
// assertions
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasCauseInstanceOf(IllegalStateException.class);
}
Take a look at this blog which covers most of the options with examples.
http://blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html
And this one explains the Java 8 Lambda option more fully:
http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

How to test ParseException that is thrown by SimpelDateFormat? [duplicate]

How can I use JUnit idiomatically to test that some code throws an exception?
While I can certainly do something like this:
#Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
I recall that there is an annotation or an Assert.xyz or something that is far less kludgy and far more in-the-spirit of JUnit for these sorts of situations.
It depends on the JUnit version and what assert libraries you use.
For JUnit5 and 4.13 see answer
If you use AssertJ or google-truth, see answer
The original answer for JUnit <= 4.12 was:
#Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
Though answer has more options for JUnit <= 4.12.
Reference:
JUnit Test-FAQ
Edit: Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows() (for JUnit 5) and Assert.assertThrows() (for JUnit 4.13+). See my other answer for details.
If you haven't migrated to JUnit 5, but can use JUnit 4.7, you can use the ExpectedException Rule:
public class FooTest {
#Rule
public final ExpectedException exception = ExpectedException.none();
#Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
}
}
This is much better than #Test(expected=IndexOutOfBoundsException.class) because the test will fail if IndexOutOfBoundsException is thrown before foo.doStuff()
See this article for details.
Be careful using expected exception, because it only asserts that the method threw that exception, not a particular line of code in the test.
I tend to use this for testing parameter validation, because such methods are usually very simple, but more complex tests might better be served with:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
Apply judgement.
in junit, there are four ways to test exception.
junit5.x
for junit5.x, you can use assertThrows as following
#Test
public void testFooThrowsIndexOutOfBoundsException() {
Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
assertEquals("expected messages", exception.getMessage());
}
junit4.x
for junit4.x, use the optional 'expected' attribute of Test annonation
#Test(expected = IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() {
foo.doStuff();
}
for junit4.x, use the ExpectedException rule
public class XxxTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testFooThrowsIndexOutOfBoundsException() {
thrown.expect(IndexOutOfBoundsException.class)
//you can test the exception message like
thrown.expectMessage("expected messages");
foo.doStuff();
}
}
you also can use the classic try/catch way widely used under junit 3 framework
#Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
fail("expected exception was not occured.");
} catch(IndexOutOfBoundsException e) {
//if execution reaches here,
//it indicates this exception was occured.
//so we need not handle it.
}
}
so
if you like junit 5, then you should like the 1st one
the 2nd way is used when you only want test the type of exception
the first and last two are used when you want test exception message further
if you use junit 3, then the 4th one is preferred
for more info, you can read this document and junit5 user guide for details.
As answered before, there are many ways of dealing with exceptions in JUnit. But with Java 8 there is another one: using Lambda Expressions. With Lambda Expressions we can achieve a syntax like this:
#Test
public void verifiesTypeAndMessage() {
assertThrown(new DummyService()::someMethod)
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasMessageStartingWith("Runtime")
.hasMessageEndingWith("occurred")
.hasMessageContaining("exception")
.hasNoCause();
}
assertThrown accepts a functional interface, whose instances can be created with lambda expressions, method references, or constructor references. assertThrown accepting that interface will expect and be ready to handle an exception.
This is relatively simple yet powerful technique.
Have a look at this blog post describing this technique: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html
The source code can be found here: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8
Disclosure: I am the author of the blog and the project.
tl;dr
post-JDK8 : Use AssertJ or custom lambdas to assert exceptional behaviour.
pre-JDK8 : I will recommend the old good try-catch block. (Don't forget to add a fail() assertion before the catch block)
Regardless of Junit 4 or JUnit 5.
the long story
It is possible to write yourself a do it yourself try-catch block or use the JUnit tools (#Test(expected = ...) or the #Rule ExpectedException JUnit rule feature).
But these ways are not so elegant and don't mix well readability wise with other tools. Moreover, JUnit tooling does have some pitfalls.
The try-catch block you have to write the block around the tested behavior and write the assertion in the catch block, that may be fine but many find that this style interrupts the reading flow of a test. Also, you need to write an Assert.fail at the end of the try block. Otherwise, the test may miss one side of the assertions; PMD, findbugs or Sonar will spot such issues.
The #Test(expected = ...) feature is interesting as you can write less code and then writing this test is supposedly less prone to coding errors. But this approach is lacking in some areas.
If the test needs to check additional things on the exception like the cause or the message (good exception messages are really important, having a precise exception type may not be enough).
Also as the expectation is placed around in the method, depending on how the tested code is written then the wrong part of the test code can throw the exception, leading to false-positive test and I'm not sure that PMD, findbugs or Sonar will give hints on such code.
#Test(expected = WantedException.class)
public void call2_should_throw_a_WantedException__not_call1() {
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
The ExpectedException rule is also an attempt to fix the previous caveats, but it feels a bit awkward to use as it uses an expectation style, EasyMock users know very well this style. It might be convenient for some, but if you follow Behaviour Driven Development (BDD) or Arrange Act Assert (AAA) principles the ExpectedException rule won't fit in those writing style. Aside from that it may suffer from the same issue as the #Test way, depending on where you place the expectation.
#Rule ExpectedException thrown = ExpectedException.none()
#Test
public void call2_should_throw_a_WantedException__not_call1() {
// expectations
thrown.expect(WantedException.class);
thrown.expectMessage("boom");
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
Even the expected exception is placed before the test statement, it breaks your reading flow if the tests follow BDD or AAA.
Also, see this comment issue on JUnit of the author of ExpectedException. JUnit 4.13-beta-2 even deprecates this mechanism:
Pull request #1519: Deprecate ExpectedException
The method Assert.assertThrows provides a nicer way for verifying exceptions. In addition, the use of ExpectedException is error-prone when used with other rules like TestWatcher because the order of rules is important in that case.
So these above options have all their load of caveats, and clearly not immune to coder errors.
There's a project I became aware of after creating this answer that looks promising, it's catch-exception.
As the description of the project says, it let a coder write in a fluent line of code catching the exception and offer this exception for the latter assertion. And you can use any assertion library like Hamcrest or AssertJ.
A rapid example taken from the home page :
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
when(myList).get(1);
// then: we expect an IndexOutOfBoundsException
then(caughtException())
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessage("Index: 1, Size: 0")
.hasNoCause();
As you can see the code is really straightforward, you catch the exception on a specific line, the then API is an alias that will use AssertJ APIs (similar to using assertThat(ex).hasNoCause()...). At some point the project relied on FEST-Assert the ancestor of AssertJ. EDIT: It seems the project is brewing a Java 8 Lambdas support.
Currently, this library has two shortcomings :
At the time of this writing, it is noteworthy to say this library is based on Mockito 1.x as it creates a mock of the tested object behind the scene. As Mockito is still not updated this library cannot work with final classes or final methods. And even if it was based on Mockito 2 in the current version, this would require to declare a global mock maker (inline-mock-maker), something that may not what you want, as this mock maker has different drawbacks that the regular mock maker.
It requires yet another test dependency.
These issues won't apply once the library supports lambdas. However, the functionality will be duplicated by the AssertJ toolset.
Taking all into account if you don't want to use the catch-exception tool, I will recommend the old good way of the try-catch block, at least up to the JDK7. And for JDK 8 users you might prefer to use AssertJ as it offers may more than just asserting exceptions.
With the JDK8, lambdas enter the test scene, and they have proved to be an interesting way to assert exceptional behaviour. AssertJ has been updated to provide a nice fluent API to assert exceptional behaviour.
And a sample test with AssertJ :
#Test
public void test_exception_approach_1() {
...
assertThatExceptionOfType(IOException.class)
.isThrownBy(() -> someBadIOOperation())
.withMessage("boom!");
}
#Test
public void test_exception_approach_2() {
...
assertThatThrownBy(() -> someBadIOOperation())
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
#Test
public void test_exception_approach_3() {
...
// when
Throwable thrown = catchThrowable(() -> someBadIOOperation());
// then
assertThat(thrown).isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
With a near-complete rewrite of JUnit 5, assertions have been improved a bit, they may prove interesting as an out of the box way to assert properly exception. But really the assertion API is still a bit poor, there's nothing outside assertThrows.
#Test
#DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
Assertions.assertEquals("...", t.getMessage());
}
As you noticed assertEquals is still returning void, and as such doesn't allow chaining assertions like AssertJ.
Also if you remember name clash with Matcher or Assert, be prepared to meet the same clash with Assertions.
I'd like to conclude that today (2017-03-03) AssertJ's ease of use, discoverable API, the rapid pace of development and as a de facto test dependency is the best solution with JDK8 regardless of the test framework (JUnit or not), prior JDKs should instead rely on try-catch blocks even if they feel clunky.
This answer has been copied from another question that don't have the same visibility, I am the same author.
Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows() (for JUnit 5) and Assert.assertThrows() (for JUnit 4.13). See
the JUnit 5 User Guide.
Here is an example that verifies an exception is thrown, and uses Truth to make assertions on the exception message:
public class FooTest {
#Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
IndexOutOfBoundsException e = assertThrows(
IndexOutOfBoundsException.class, foo::doStuff);
assertThat(e).hasMessageThat().contains("woops!");
}
}
The advantages over the approaches in the other answers are:
Built into JUnit
You get a useful exception message if the code in the lambda doesn't throw an exception, and a stacktrace if it throws a different exception
Concise
Allows your tests to follow Arrange-Act-Assert
You can precisely indicate what code you are expecting to throw the exception
You don't need to list the expected exception in the throws clause
You can use the assertion framework of your choice to make assertions about the caught exception
Update: JUnit5 has an improvement for exceptions testing: assertThrows.
The following example is from: Junit 5 User Guide
import static org.junit.jupiter.api.Assertions.assertThrows;
#Test
void exceptionTesting() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
Original answer using JUnit 4.
There are several ways to test that an exception is thrown. I have also discussed the below options in my post How to write great unit tests with JUnit
Set the expected parameter #Test(expected = FileNotFoundException.class).
#Test(expected = FileNotFoundException.class)
public void testReadFile() {
myClass.readFile("test.txt");
}
Using try catch
public void testReadFile() {
try {
myClass.readFile("test.txt");
fail("Expected a FileNotFoundException to be thrown");
} catch (FileNotFoundException e) {
assertThat(e.getMessage(), is("The file test.txt does not exist!"));
}
}
Testing with ExpectedException Rule.
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testReadFile() throws FileNotFoundException {
thrown.expect(FileNotFoundException.class);
thrown.expectMessage(startsWith("The file test.txt"));
myClass.readFile("test.txt");
}
You could read more about exceptions testing in JUnit4 wiki for Exception testing and bad.robot - Expecting Exceptions JUnit Rule.
How about this: catch a very general exception, make sure it makes it out of the catch block, then assert that the class of the exception is what you expect it to be. This assert will fail if a) the exception is of the wrong type (eg. if you got a Null Pointer instead) and b) the exception wasn't ever thrown.
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
Using an AssertJ assertion, which can be used alongside JUnit:
import static org.assertj.core.api.Assertions.*;
#Test
public void testFooThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
assertThatThrownBy(() -> foo.doStuff())
.isInstanceOf(IndexOutOfBoundsException.class);
}
It's better than #Test(expected=IndexOutOfBoundsException.class) because it guarantees the expected line in the test threw the exception and lets you check more details about the exception, such as message, easier:
assertThatThrownBy(() ->
{
throw new Exception("boom!");
})
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
Maven/Gradle instructions here.
BDD Style Solution: JUnit 4 + Catch Exception + AssertJ
import static com.googlecode.catchexception.apis.BDDCatchException.*;
#Test
public void testFooThrowsIndexOutOfBoundsException() {
when(() -> foo.doStuff());
then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);
}
Dependencies
eu.codearte.catch-exception:catch-exception:2.0
To solve the same problem I did set up a small project:
http://code.google.com/p/catch-exception/
Using this little helper you would write
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
This is less verbose than the ExpectedException rule of JUnit 4.7.
In comparison to the solution provided by skaffman, you can specify in which line of code you expect the exception. I hope this helps.
You can also do this:
#Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
IMHO, the best way to check for exceptions in JUnit is the try/catch/fail/assert pattern:
// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
sut.doThing();
fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
// otherwise you may catch an exception for a dependency unexpectedly
// a strong assertion on the message,
// in case the exception comes from anywhere an unexpected line of code,
// especially important if your checking IllegalArgumentExceptions
assertEquals("the message I get", e.getMessage());
}
The assertTrue might be a bit strong for some people, so assertThat(e.getMessage(), containsString("the message"); might be preferable.
JUnit 5 Solution
import static org.junit.jupiter.api.Assertions.assertThrows;
#Test
void testFooThrowsIndexOutOfBoundsException() {
IndexOutOfBoundsException exception = expectThrows(IndexOutOfBoundsException.class, foo::doStuff);
assertEquals("some message", exception.getMessage());
}
More Infos about JUnit 5 on http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
The most flexible and elegant answer for Junit 4 I found in the Mkyong blog. It has the flexibility of the try/catch using the #Rule annotation. I like this approach because you can read specific attributes of a customized exception.
package com.mkyong;
import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;
public class Exception3Test {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testNameNotFoundException() throws NameNotFoundException {
//test specific type of exception
thrown.expect(NameNotFoundException.class);
//test message
thrown.expectMessage(is("Name is empty!"));
//test detail
thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined.
thrown.expect(hasProperty("errCode", is(666)));
CustomerService cust = new CustomerService();
cust.findByName("");
}
}
I tried many of the methods here, but they were either complicated or didn't quite meet my requirements. In fact, one can write a helper method quite simply:
public class ExceptionAssertions {
public static void assertException(BlastContainer blastContainer ) {
boolean caughtException = false;
try {
blastContainer.test();
} catch( Exception e ) {
caughtException = true;
}
if( !caughtException ) {
throw new AssertionFailedError("exception expected to be thrown, but was not");
}
}
public static interface BlastContainer {
public void test() throws Exception;
}
}
Use it like this:
assertException(new BlastContainer() {
#Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
Zero dependencies: no need for mockito, no need powermock; and works just fine with final classes.
JUnit has built-in support for this, with an "expected" attribute.
Java 8 solution
If you would like a solution which:
Utilizes Java 8 lambdas
Does not depend on any JUnit magic
Allows you to check for multiple exceptions within a single test method
Checks for an exception being thrown by a specific set of lines within your test method instead of any unknown line in the entire test method
Yields the actual exception object that was thrown so that you can further examine it
Here is a utility function that I wrote:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows testing for "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
#SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
(taken from my blog)
Use it as follows:
#Test
public void testMyFunction()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
myFunction();
} );
assert e.getMessage().equals( "I haz fail!" );
}
public void myFunction()
{
throw new RuntimeException( "I haz fail!" );
}
In my case I always get RuntimeException from db, but messages differ. And exception need to be handled respectively. Here is how I tested it:
#Test
public void testThrowsExceptionWhenWrongSku() {
// Given
String articleSimpleSku = "999-999";
int amountOfTransactions = 1;
Exception exception = null;
// When
try {
createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
} catch (RuntimeException e) {
exception = e;
}
// Then
shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}
private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
assertNotNull(e);
assertTrue(e.getMessage().contains(message));
}
Just make a Matcher that can be turned off and on, like this:
public class ExceptionMatcher extends BaseMatcher<Throwable> {
private boolean active = true;
private Class<? extends Throwable> throwable;
public ExceptionMatcher(Class<? extends Throwable> throwable) {
this.throwable = throwable;
}
public void on() {
this.active = true;
}
public void off() {
this.active = false;
}
#Override
public boolean matches(Object object) {
return active && throwable.isAssignableFrom(object.getClass());
}
#Override
public void describeTo(Description description) {
description.appendText("not the covered exception type");
}
}
To use it:
add public ExpectedException exception = ExpectedException.none();,
then:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
In JUnit 4 or later you can test the exceptions as follows
#Rule
public ExpectedException exceptions = ExpectedException.none();
this provides a lot of features which can be used to improve our JUnit tests. If you see the below example I am testing 3 things on the exception.
The Type of exception thrown
The exception Message
The cause of the exception
public class MyTest {
#Rule
public ExpectedException exceptions = ExpectedException.none();
ClassUnderTest classUnderTest;
#Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
}
#Test
public void testAppleisSweetAndRed() throws Exception {
exceptions.expect(Exception.class);
exceptions.expectMessage("this is the exception message");
exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
classUnderTest.methodUnderTest("param1", "param2");
}
}
We can use an assertion fail after the method that must return an exception:
try{
methodThatThrowMyException();
Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
// Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
// In case of verifying the error message
MyException myException = (MyException) exception;
assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}
Additionally to what NamShubWriter has said, make sure that:
The ExpectedException instance is public (Related Question)
The ExpectedException isn't instantiated in say, the #Before method. This post clearly explains all the intricacies of JUnit's order of execution.
Do not do this:
#Rule
public ExpectedException expectedException;
#Before
public void setup()
{
expectedException = ExpectedException.none();
}
Finally, this blog post clearly illustrates how to assert that a certain exception is thrown.
Junit4 solution with Java8 is to use this function:
public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
try {
funky.call();
} catch (Throwable e) {
if (expectedException.isInstance(e)) {
return e;
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}
Usage is then:
assertThrows(ValidationException.class,
() -> finalObject.checkSomething(null));
Note that the only limitation is to use a final object reference in lambda expression.
This solution allows to continue test assertions instead of expecting thowable at method level using #Test(expected = IndexOutOfBoundsException.class) solution.
I recomend library assertj-core to handle exception in junit test
In java 8, like this:
//given
//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));
//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
JUnit framework has assertThrows() method:
ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
for JUnit 5 it's in org.junit.jupiter.api.Assertions class;
for JUnit 4.13 it's in org.junit.Assert class;
for earlier versions of JUnit 4: just add reference on org.junit.jupiter:junit-jupiter-api to your project and you'll get perfectly well working version from JUnit 5.
Take for example, you want to write Junit for below mentioned code fragment
public int divideByZeroDemo(int a,int b){
return a/b;
}
public void exceptionWithMessage(String [] arr){
throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}
The above code is to test for some unknown exception that may occur and the below one is to assert some exception with custom message.
#Rule
public ExpectedException exception=ExpectedException.none();
private Demo demo;
#Before
public void setup(){
demo=new Demo();
}
#Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {
demo.divideByZeroDemo(5, 0);
}
#Test
public void testExceptionWithMessage(){
exception.expectMessage("Array is out of bound");
exception.expect(ArrayIndexOutOfBoundsException.class);
demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}
With Java 8 you can create a method taking a code to check and expected exception as parameters:
private void expectException(Runnable r, Class<?> clazz) {
try {
r.run();
fail("Expected: " + clazz.getSimpleName() + " but not thrown");
} catch (Exception e) {
if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
}
}
and then inside your test:
expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);
Benefits:
not relying on any library
localised check - more precise and allows to have multiple assertions like this within one test if needed
easy to use
#Test(expectedException=IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() throws Exception {
doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
throw e;
}
}
Here is another way to check method thrown correct exception or not.

Junit expect assertion called [duplicate]

How can I use JUnit idiomatically to test that some code throws an exception?
While I can certainly do something like this:
#Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
I recall that there is an annotation or an Assert.xyz or something that is far less kludgy and far more in-the-spirit of JUnit for these sorts of situations.
It depends on the JUnit version and what assert libraries you use.
For JUnit5 and 4.13 see answer
If you use AssertJ or google-truth, see answer
The original answer for JUnit <= 4.12 was:
#Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
ArrayList emptyList = new ArrayList();
Object o = emptyList.get(0);
}
Though answer has more options for JUnit <= 4.12.
Reference:
JUnit Test-FAQ
Edit: Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows() (for JUnit 5) and Assert.assertThrows() (for JUnit 4.13+). See my other answer for details.
If you haven't migrated to JUnit 5, but can use JUnit 4.7, you can use the ExpectedException Rule:
public class FooTest {
#Rule
public final ExpectedException exception = ExpectedException.none();
#Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
exception.expect(IndexOutOfBoundsException.class);
foo.doStuff();
}
}
This is much better than #Test(expected=IndexOutOfBoundsException.class) because the test will fail if IndexOutOfBoundsException is thrown before foo.doStuff()
See this article for details.
Be careful using expected exception, because it only asserts that the method threw that exception, not a particular line of code in the test.
I tend to use this for testing parameter validation, because such methods are usually very simple, but more complex tests might better be served with:
try {
methodThatShouldThrow();
fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}
Apply judgement.
in junit, there are four ways to test exception.
junit5.x
for junit5.x, you can use assertThrows as following
#Test
public void testFooThrowsIndexOutOfBoundsException() {
Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
assertEquals("expected messages", exception.getMessage());
}
junit4.x
for junit4.x, use the optional 'expected' attribute of Test annonation
#Test(expected = IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() {
foo.doStuff();
}
for junit4.x, use the ExpectedException rule
public class XxxTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testFooThrowsIndexOutOfBoundsException() {
thrown.expect(IndexOutOfBoundsException.class)
//you can test the exception message like
thrown.expectMessage("expected messages");
foo.doStuff();
}
}
you also can use the classic try/catch way widely used under junit 3 framework
#Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
fail("expected exception was not occured.");
} catch(IndexOutOfBoundsException e) {
//if execution reaches here,
//it indicates this exception was occured.
//so we need not handle it.
}
}
so
if you like junit 5, then you should like the 1st one
the 2nd way is used when you only want test the type of exception
the first and last two are used when you want test exception message further
if you use junit 3, then the 4th one is preferred
for more info, you can read this document and junit5 user guide for details.
As answered before, there are many ways of dealing with exceptions in JUnit. But with Java 8 there is another one: using Lambda Expressions. With Lambda Expressions we can achieve a syntax like this:
#Test
public void verifiesTypeAndMessage() {
assertThrown(new DummyService()::someMethod)
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasMessageStartingWith("Runtime")
.hasMessageEndingWith("occurred")
.hasMessageContaining("exception")
.hasNoCause();
}
assertThrown accepts a functional interface, whose instances can be created with lambda expressions, method references, or constructor references. assertThrown accepting that interface will expect and be ready to handle an exception.
This is relatively simple yet powerful technique.
Have a look at this blog post describing this technique: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html
The source code can be found here: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8
Disclosure: I am the author of the blog and the project.
tl;dr
post-JDK8 : Use AssertJ or custom lambdas to assert exceptional behaviour.
pre-JDK8 : I will recommend the old good try-catch block. (Don't forget to add a fail() assertion before the catch block)
Regardless of Junit 4 or JUnit 5.
the long story
It is possible to write yourself a do it yourself try-catch block or use the JUnit tools (#Test(expected = ...) or the #Rule ExpectedException JUnit rule feature).
But these ways are not so elegant and don't mix well readability wise with other tools. Moreover, JUnit tooling does have some pitfalls.
The try-catch block you have to write the block around the tested behavior and write the assertion in the catch block, that may be fine but many find that this style interrupts the reading flow of a test. Also, you need to write an Assert.fail at the end of the try block. Otherwise, the test may miss one side of the assertions; PMD, findbugs or Sonar will spot such issues.
The #Test(expected = ...) feature is interesting as you can write less code and then writing this test is supposedly less prone to coding errors. But this approach is lacking in some areas.
If the test needs to check additional things on the exception like the cause or the message (good exception messages are really important, having a precise exception type may not be enough).
Also as the expectation is placed around in the method, depending on how the tested code is written then the wrong part of the test code can throw the exception, leading to false-positive test and I'm not sure that PMD, findbugs or Sonar will give hints on such code.
#Test(expected = WantedException.class)
public void call2_should_throw_a_WantedException__not_call1() {
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
The ExpectedException rule is also an attempt to fix the previous caveats, but it feels a bit awkward to use as it uses an expectation style, EasyMock users know very well this style. It might be convenient for some, but if you follow Behaviour Driven Development (BDD) or Arrange Act Assert (AAA) principles the ExpectedException rule won't fit in those writing style. Aside from that it may suffer from the same issue as the #Test way, depending on where you place the expectation.
#Rule ExpectedException thrown = ExpectedException.none()
#Test
public void call2_should_throw_a_WantedException__not_call1() {
// expectations
thrown.expect(WantedException.class);
thrown.expectMessage("boom");
// init tested
tested.call1(); // may throw a WantedException
// call to be actually tested
tested.call2(); // the call that is supposed to raise an exception
}
Even the expected exception is placed before the test statement, it breaks your reading flow if the tests follow BDD or AAA.
Also, see this comment issue on JUnit of the author of ExpectedException. JUnit 4.13-beta-2 even deprecates this mechanism:
Pull request #1519: Deprecate ExpectedException
The method Assert.assertThrows provides a nicer way for verifying exceptions. In addition, the use of ExpectedException is error-prone when used with other rules like TestWatcher because the order of rules is important in that case.
So these above options have all their load of caveats, and clearly not immune to coder errors.
There's a project I became aware of after creating this answer that looks promising, it's catch-exception.
As the description of the project says, it let a coder write in a fluent line of code catching the exception and offer this exception for the latter assertion. And you can use any assertion library like Hamcrest or AssertJ.
A rapid example taken from the home page :
// given: an empty list
List myList = new ArrayList();
// when: we try to get the first element of the list
when(myList).get(1);
// then: we expect an IndexOutOfBoundsException
then(caughtException())
.isInstanceOf(IndexOutOfBoundsException.class)
.hasMessage("Index: 1, Size: 0")
.hasNoCause();
As you can see the code is really straightforward, you catch the exception on a specific line, the then API is an alias that will use AssertJ APIs (similar to using assertThat(ex).hasNoCause()...). At some point the project relied on FEST-Assert the ancestor of AssertJ. EDIT: It seems the project is brewing a Java 8 Lambdas support.
Currently, this library has two shortcomings :
At the time of this writing, it is noteworthy to say this library is based on Mockito 1.x as it creates a mock of the tested object behind the scene. As Mockito is still not updated this library cannot work with final classes or final methods. And even if it was based on Mockito 2 in the current version, this would require to declare a global mock maker (inline-mock-maker), something that may not what you want, as this mock maker has different drawbacks that the regular mock maker.
It requires yet another test dependency.
These issues won't apply once the library supports lambdas. However, the functionality will be duplicated by the AssertJ toolset.
Taking all into account if you don't want to use the catch-exception tool, I will recommend the old good way of the try-catch block, at least up to the JDK7. And for JDK 8 users you might prefer to use AssertJ as it offers may more than just asserting exceptions.
With the JDK8, lambdas enter the test scene, and they have proved to be an interesting way to assert exceptional behaviour. AssertJ has been updated to provide a nice fluent API to assert exceptional behaviour.
And a sample test with AssertJ :
#Test
public void test_exception_approach_1() {
...
assertThatExceptionOfType(IOException.class)
.isThrownBy(() -> someBadIOOperation())
.withMessage("boom!");
}
#Test
public void test_exception_approach_2() {
...
assertThatThrownBy(() -> someBadIOOperation())
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
#Test
public void test_exception_approach_3() {
...
// when
Throwable thrown = catchThrowable(() -> someBadIOOperation());
// then
assertThat(thrown).isInstanceOf(Exception.class)
.hasMessageContaining("boom");
}
With a near-complete rewrite of JUnit 5, assertions have been improved a bit, they may prove interesting as an out of the box way to assert properly exception. But really the assertion API is still a bit poor, there's nothing outside assertThrows.
#Test
#DisplayName("throws EmptyStackException when peeked")
void throwsExceptionWhenPeeked() {
Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
Assertions.assertEquals("...", t.getMessage());
}
As you noticed assertEquals is still returning void, and as such doesn't allow chaining assertions like AssertJ.
Also if you remember name clash with Matcher or Assert, be prepared to meet the same clash with Assertions.
I'd like to conclude that today (2017-03-03) AssertJ's ease of use, discoverable API, the rapid pace of development and as a de facto test dependency is the best solution with JDK8 regardless of the test framework (JUnit or not), prior JDKs should instead rely on try-catch blocks even if they feel clunky.
This answer has been copied from another question that don't have the same visibility, I am the same author.
Now that JUnit 5 and JUnit 4.13 have been released, the best option would be to use Assertions.assertThrows() (for JUnit 5) and Assert.assertThrows() (for JUnit 4.13). See
the JUnit 5 User Guide.
Here is an example that verifies an exception is thrown, and uses Truth to make assertions on the exception message:
public class FooTest {
#Test
public void doStuffThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
IndexOutOfBoundsException e = assertThrows(
IndexOutOfBoundsException.class, foo::doStuff);
assertThat(e).hasMessageThat().contains("woops!");
}
}
The advantages over the approaches in the other answers are:
Built into JUnit
You get a useful exception message if the code in the lambda doesn't throw an exception, and a stacktrace if it throws a different exception
Concise
Allows your tests to follow Arrange-Act-Assert
You can precisely indicate what code you are expecting to throw the exception
You don't need to list the expected exception in the throws clause
You can use the assertion framework of your choice to make assertions about the caught exception
Update: JUnit5 has an improvement for exceptions testing: assertThrows.
The following example is from: Junit 5 User Guide
import static org.junit.jupiter.api.Assertions.assertThrows;
#Test
void exceptionTesting() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("a message");
});
assertEquals("a message", exception.getMessage());
}
Original answer using JUnit 4.
There are several ways to test that an exception is thrown. I have also discussed the below options in my post How to write great unit tests with JUnit
Set the expected parameter #Test(expected = FileNotFoundException.class).
#Test(expected = FileNotFoundException.class)
public void testReadFile() {
myClass.readFile("test.txt");
}
Using try catch
public void testReadFile() {
try {
myClass.readFile("test.txt");
fail("Expected a FileNotFoundException to be thrown");
} catch (FileNotFoundException e) {
assertThat(e.getMessage(), is("The file test.txt does not exist!"));
}
}
Testing with ExpectedException Rule.
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testReadFile() throws FileNotFoundException {
thrown.expect(FileNotFoundException.class);
thrown.expectMessage(startsWith("The file test.txt"));
myClass.readFile("test.txt");
}
You could read more about exceptions testing in JUnit4 wiki for Exception testing and bad.robot - Expecting Exceptions JUnit Rule.
How about this: catch a very general exception, make sure it makes it out of the catch block, then assert that the class of the exception is what you expect it to be. This assert will fail if a) the exception is of the wrong type (eg. if you got a Null Pointer instead) and b) the exception wasn't ever thrown.
public void testFooThrowsIndexOutOfBoundsException() {
Throwable e = null;
try {
foo.doStuff();
} catch (Throwable ex) {
e = ex;
}
assertTrue(e instanceof IndexOutOfBoundsException);
}
Using an AssertJ assertion, which can be used alongside JUnit:
import static org.assertj.core.api.Assertions.*;
#Test
public void testFooThrowsIndexOutOfBoundsException() {
Foo foo = new Foo();
assertThatThrownBy(() -> foo.doStuff())
.isInstanceOf(IndexOutOfBoundsException.class);
}
It's better than #Test(expected=IndexOutOfBoundsException.class) because it guarantees the expected line in the test threw the exception and lets you check more details about the exception, such as message, easier:
assertThatThrownBy(() ->
{
throw new Exception("boom!");
})
.isInstanceOf(Exception.class)
.hasMessageContaining("boom");
Maven/Gradle instructions here.
BDD Style Solution: JUnit 4 + Catch Exception + AssertJ
import static com.googlecode.catchexception.apis.BDDCatchException.*;
#Test
public void testFooThrowsIndexOutOfBoundsException() {
when(() -> foo.doStuff());
then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);
}
Dependencies
eu.codearte.catch-exception:catch-exception:2.0
To solve the same problem I did set up a small project:
http://code.google.com/p/catch-exception/
Using this little helper you would write
verifyException(foo, IndexOutOfBoundsException.class).doStuff();
This is less verbose than the ExpectedException rule of JUnit 4.7.
In comparison to the solution provided by skaffman, you can specify in which line of code you expect the exception. I hope this helps.
You can also do this:
#Test
public void testFooThrowsIndexOutOfBoundsException() {
try {
foo.doStuff();
assert false;
} catch (IndexOutOfBoundsException e) {
assert true;
}
}
IMHO, the best way to check for exceptions in JUnit is the try/catch/fail/assert pattern:
// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
sut.doThing();
fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
// otherwise you may catch an exception for a dependency unexpectedly
// a strong assertion on the message,
// in case the exception comes from anywhere an unexpected line of code,
// especially important if your checking IllegalArgumentExceptions
assertEquals("the message I get", e.getMessage());
}
The assertTrue might be a bit strong for some people, so assertThat(e.getMessage(), containsString("the message"); might be preferable.
JUnit 5 Solution
import static org.junit.jupiter.api.Assertions.assertThrows;
#Test
void testFooThrowsIndexOutOfBoundsException() {
IndexOutOfBoundsException exception = expectThrows(IndexOutOfBoundsException.class, foo::doStuff);
assertEquals("some message", exception.getMessage());
}
More Infos about JUnit 5 on http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions
The most flexible and elegant answer for Junit 4 I found in the Mkyong blog. It has the flexibility of the try/catch using the #Rule annotation. I like this approach because you can read specific attributes of a customized exception.
package com.mkyong;
import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;
public class Exception3Test {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testNameNotFoundException() throws NameNotFoundException {
//test specific type of exception
thrown.expect(NameNotFoundException.class);
//test message
thrown.expectMessage(is("Name is empty!"));
//test detail
thrown.expect(hasProperty("errCode")); //make sure getters n setters are defined.
thrown.expect(hasProperty("errCode", is(666)));
CustomerService cust = new CustomerService();
cust.findByName("");
}
}
I tried many of the methods here, but they were either complicated or didn't quite meet my requirements. In fact, one can write a helper method quite simply:
public class ExceptionAssertions {
public static void assertException(BlastContainer blastContainer ) {
boolean caughtException = false;
try {
blastContainer.test();
} catch( Exception e ) {
caughtException = true;
}
if( !caughtException ) {
throw new AssertionFailedError("exception expected to be thrown, but was not");
}
}
public static interface BlastContainer {
public void test() throws Exception;
}
}
Use it like this:
assertException(new BlastContainer() {
#Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
Zero dependencies: no need for mockito, no need powermock; and works just fine with final classes.
JUnit has built-in support for this, with an "expected" attribute.
Java 8 solution
If you would like a solution which:
Utilizes Java 8 lambdas
Does not depend on any JUnit magic
Allows you to check for multiple exceptions within a single test method
Checks for an exception being thrown by a specific set of lines within your test method instead of any unknown line in the entire test method
Yields the actual exception object that was thrown so that you can further examine it
Here is a utility function that I wrote:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows testing for "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
#SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
(taken from my blog)
Use it as follows:
#Test
public void testMyFunction()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
myFunction();
} );
assert e.getMessage().equals( "I haz fail!" );
}
public void myFunction()
{
throw new RuntimeException( "I haz fail!" );
}
In my case I always get RuntimeException from db, but messages differ. And exception need to be handled respectively. Here is how I tested it:
#Test
public void testThrowsExceptionWhenWrongSku() {
// Given
String articleSimpleSku = "999-999";
int amountOfTransactions = 1;
Exception exception = null;
// When
try {
createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
} catch (RuntimeException e) {
exception = e;
}
// Then
shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}
private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
assertNotNull(e);
assertTrue(e.getMessage().contains(message));
}
Just make a Matcher that can be turned off and on, like this:
public class ExceptionMatcher extends BaseMatcher<Throwable> {
private boolean active = true;
private Class<? extends Throwable> throwable;
public ExceptionMatcher(Class<? extends Throwable> throwable) {
this.throwable = throwable;
}
public void on() {
this.active = true;
}
public void off() {
this.active = false;
}
#Override
public boolean matches(Object object) {
return active && throwable.isAssignableFrom(object.getClass());
}
#Override
public void describeTo(Description description) {
description.appendText("not the covered exception type");
}
}
To use it:
add public ExpectedException exception = ExpectedException.none();,
then:
ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();
In JUnit 4 or later you can test the exceptions as follows
#Rule
public ExpectedException exceptions = ExpectedException.none();
this provides a lot of features which can be used to improve our JUnit tests. If you see the below example I am testing 3 things on the exception.
The Type of exception thrown
The exception Message
The cause of the exception
public class MyTest {
#Rule
public ExpectedException exceptions = ExpectedException.none();
ClassUnderTest classUnderTest;
#Before
public void setUp() throws Exception {
classUnderTest = new ClassUnderTest();
}
#Test
public void testAppleisSweetAndRed() throws Exception {
exceptions.expect(Exception.class);
exceptions.expectMessage("this is the exception message");
exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
classUnderTest.methodUnderTest("param1", "param2");
}
}
We can use an assertion fail after the method that must return an exception:
try{
methodThatThrowMyException();
Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
// Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
// In case of verifying the error message
MyException myException = (MyException) exception;
assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}
Additionally to what NamShubWriter has said, make sure that:
The ExpectedException instance is public (Related Question)
The ExpectedException isn't instantiated in say, the #Before method. This post clearly explains all the intricacies of JUnit's order of execution.
Do not do this:
#Rule
public ExpectedException expectedException;
#Before
public void setup()
{
expectedException = ExpectedException.none();
}
Finally, this blog post clearly illustrates how to assert that a certain exception is thrown.
Junit4 solution with Java8 is to use this function:
public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
try {
funky.call();
} catch (Throwable e) {
if (expectedException.isInstance(e)) {
return e;
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
}
throw new AssertionError(
String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}
Usage is then:
assertThrows(ValidationException.class,
() -> finalObject.checkSomething(null));
Note that the only limitation is to use a final object reference in lambda expression.
This solution allows to continue test assertions instead of expecting thowable at method level using #Test(expected = IndexOutOfBoundsException.class) solution.
I recomend library assertj-core to handle exception in junit test
In java 8, like this:
//given
//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));
//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);
JUnit framework has assertThrows() method:
ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
for JUnit 5 it's in org.junit.jupiter.api.Assertions class;
for JUnit 4.13 it's in org.junit.Assert class;
for earlier versions of JUnit 4: just add reference on org.junit.jupiter:junit-jupiter-api to your project and you'll get perfectly well working version from JUnit 5.
Take for example, you want to write Junit for below mentioned code fragment
public int divideByZeroDemo(int a,int b){
return a/b;
}
public void exceptionWithMessage(String [] arr){
throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}
The above code is to test for some unknown exception that may occur and the below one is to assert some exception with custom message.
#Rule
public ExpectedException exception=ExpectedException.none();
private Demo demo;
#Before
public void setup(){
demo=new Demo();
}
#Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {
demo.divideByZeroDemo(5, 0);
}
#Test
public void testExceptionWithMessage(){
exception.expectMessage("Array is out of bound");
exception.expect(ArrayIndexOutOfBoundsException.class);
demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}
With Java 8 you can create a method taking a code to check and expected exception as parameters:
private void expectException(Runnable r, Class<?> clazz) {
try {
r.run();
fail("Expected: " + clazz.getSimpleName() + " but not thrown");
} catch (Exception e) {
if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
}
}
and then inside your test:
expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);
Benefits:
not relying on any library
localised check - more precise and allows to have multiple assertions like this within one test if needed
easy to use
#Test(expectedException=IndexOutOfBoundsException.class)
public void testFooThrowsIndexOutOfBoundsException() throws Exception {
doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
throw e;
}
}
Here is another way to check method thrown correct exception or not.

How to test that a exception is thrown and caught in junit

I need to test the following code:
try{
while((testBean = csvReader.read(TestBean.class,headers,getCellProcessors()))!=null){
System.out.println("no excpetion");
i=5;
}
}catch(SuperCsvException csvExc){
System.out.println("superCSV excpetion");
i=0;
}catch(Exception ex){
System.out.println("excpetion");
i=0;
}
How to test that whether SuperCsvException is thrown and caught.
JUnit 4 supports this
#Test(expected=<YourExpectedException>.class)
public void testExceptionThrown() {
// call the method that throws exception
}
Either the exception is expected or it's not expected. If expected then you need something like this:
try {
doSomething();
fail("No exception thrown");
}
catch (MyException e) {
// expected
}
The "new" JUnit way of expecting exceptions is the way of rules:
public class ThisIsTheTestClass {
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testingSomeBehaviorThatShouldThrowAnException() throws SuperCsvException {
exception.expect(SuperCsvException.class);
// Put your testing effort here (setup, call, assertions, ...).
}
}
Look at some information about rules, if interested further.
JUnit 4 has support for this. You can declare your unit test as:
#Test(expected=SuperCsvException.class)
public void _testSuperCsvException() {
// call to function containing your code
}
My personal experience is always like
boolean caught = false;
try {
runCodeToThrowException();
} catch (MyException e) {
caught = true;
}
assertTrue(caught);
The reason I dislike to have JUnit handle it is I couldn't control exactly where and how this exception is thrown. That might not be good if I am trying to catch anything generic in a big trunk of code, e.g. IllegalArgumentException.
Your testing approach is wrong. You should consider each method or class you are testing as a unit that has a specification, an accessible interface (non private methods and fields) and an implementation. You should test that the unit, when manipulated through its accessible interface, conforms to its specification. You should not test that the unit has a particular implementation. You may use your knowledge of the implementation to guide your selection of test cases, to choose cases that are likely to be incorrectly implemented.
So in your case, the fact that an exception can be thrown is an implementation detail. You would be wise to have a test case that will also cause that exception to be thrown. As your code tries to catch the exception, I guess this is because the specification of your method says that the method should not throw any exceptions if there is a problem with csvReader. So you could have a test case that sets up csvReader to throw an exception. JUnit will fail the test if the method does throw the exception.
Note the difference: that test case does not test that the exception is thrown and caught (an implementation detail); it tests that the method does not throw or propagate an exception in the situation that a call to csvReader.read will throw an exception. The implementation is allowed to satisfy that constraint by catching the exception or by refraining from calling csvReader.read.
If SuperCsvException is subclass of Exception try something like this:
Exception ex=null;
try {
while ((testBean = csvReader.read(TestBean.class, headers, getCellProcessors())) != null) {
System.out.println("no excpetion");
i = 5;
}
} catch (SuperCsvException csvExc) {
System.out.println("superCSV excpetion");
i = 0;
ex=csvExc;
} catch (Exception ex) {
System.out.println("excpetion");
i = 0;
}
Assert.assertNotNull(ex);

JUnit4 and exception handeling

The following code does not compile, becouse of unreachable catch block.
I want write "tues" function and call it in many other unit test functions.
Is that possible and how to implement that?
private void catchException(boolean condition) {
try
{
assertTrue(condition);
}
catch (SomeException e)
{
fail("exception = " + e.getMessage());
}
}
Thanks!
There is zero need to catch an exception within a test method to fail it:
public Object methodUnderTest() throws SomeException {
...
}
#Test
public void testMethod() throws SomeException() {
Object obj = methodUnderTest();
assert...
}
If SomeException is thrown by methodUnderTest(), testMethod() will fail.
The problem with your code is that assertTrue does not throw SomeException, if you substitute it with the function that does, it will compile.
I'm not entirely sure what you're asking here, but there are a couple things wrong with the code you posted.
You can only have a catch block for a checked exception if the code in the try can potentially throw an exception of the same type you are catching. Since checked exceptions must be declared in the throws clause of a method, you can check to see if any of the methods you are calling throw the exception types you are catching. From the JUnit documentation on assertTrue:
public static void assertTrue(boolean condition)
You can see it doesn't throw any checked exceptions.
Also, calling fail() in a catch block in a JUnit test is not really necessary. A unit test will automatically fail if an uncaught exception is thrown.
Just add throws WhateverException to your test signature and the test will fail if an exception is thrown.
It is actually not really clear what you what to achieve with your code. If you want to have a nicely formatted message in the exception fired by jUnit if your assert fails then consider writing it in this way:
assertTrue("Condition should hold because....", conditionToCheck);
In this way jUnit will print the message you provided if the check fails. I highly recommend this, especially if you have lots of tests because it
helps you to quickly identify the problem
helps your team member to understand the purpose of your assert
Modifying SomeException by Exception will cause the code to compile.
Obviously my question is not clear.
I have many unit tests and all methods are throwing same exception with different error message. "SomeException" is exception I must catch and read error message from it.
What I want to achive is to write one method which will be common to all unit tests and where I could print error message.
Now unit tests looks like this
public void test_something()
{
try
{
assertTrue(bw.doSomething("test"));
}
catch (SomeException e)
{
fail("exception = " + e.getReason());
}
}
public void test_something1()
{
IBroadworks bw = getSomehting1();
try
{
assertTrue(bw.doSomething1("test1"));
}
catch (SomeException e)
{
fail("exception = " + e.getReason());
}
}
...
So below code is repeating in all unit tests and that is not ok.
...
try{
assertTrue(condition);
}
catch (SomeException e)
{
fail("exception = " + e.getReason());
}
...

Categories

Resources