I've got this simple method:
public int divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("Division by 0");
} else {
return a / b;
}
}
and I'd like to JUnit test it.
I've done as follows:
#Test(expected = ArithmeticException.class) // Expected this exc
public void testDivideWhenDivisorIsZero() {
int result = c.divide(1, 0);
}
which "returns" a green bar line ("tests finished successfully").
Is this a correct way to JUnit test this method or should I have put a try-catch clause in that test?
EDIT
Would this JUnit test be equivalent with the following?
#Test
public void testDivideWhenDivisorIsZero() {
try{
c.divide(1, 0);
fail("Expected ArithmeticException");
} catch(ArithmeticException e) {
}
}
Your test looks correct, and you should not use try..catch block in unit test. there are many ways, one of them is yours. But for your method I would like to use :
try {
return a / b;
} catch (ArithmeticException e) {
throw new ArithmeticException("Division by 0");
}
Let the exception be thrown, and catch it. it is more clean than checking the value before any action(which that case can be rare to happen)
The way you did this seems fine to me.
It should fit your need in this case. Nonetheless I personally prefering to do it with a try-catch-block. Which as you proposed are pretty equivalent. I think you've a few advantages if you do with the try-catch-block.
First of all, you can assert, if the errormessage of the thrown exception is actually as you've excepted and in addition you can be sure, that the exception actually happened during your method-under-test and not during your init-logic.
To get this a little bit clearer:
public int divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("Division by 0");
} else if(a<b){
//I know, that this condition is pretty senseless. It's for demonstration only.
throw new ArithmeticException("a is smaller than b");
} else{
return a / b;
}
}
Then you can test your method like this and you can be sure, that the correct Exception was thrown:
#Test
public void testDivideWhenDivisorIsZero() {
try{
c.divide(1, 2);
fail("Expected ArithmeticException");
} catch(Exception e) {
if(e instanceof ArithmeticException){
Assert.assertTrue(e.getMessage().equals("a is smaller than b"));
}else{
fail("The wrong Exception was thrown" + e.toString())
}
}
}
But as I said your attempt fits absolutely the needs.
Production code:
Neither catching nor declaring the exception is necessary, and I recommend avoiding both.
public static int divide(int a, int b) {
return a / b;
}
If you want to communicate to your API user that an ArithmeticException can be thrown, then you should do it in the javadoc.
Testcode:
JUnit5 made asserting exceptions much more easy.
#Test
void divide_whenDenominatorIsZero_shouldThrow() {
assertThrows(ArithmeticException.class, () -> divide(1, 0));
}
Hello i have 30 exception that are thrown by 30 values I pass to my test on the same method which takes the input,but it seems I cannot put the exception in the catch block,is there any workaround?
#DataProvider
public Object[][] providedInfo()
{
return new Object[][]
{
{MyGuests1.class,SQLException.class} //and many more
};
}
#Test(dataProvider="providedInfo")
public void f(Class c , Throwable ex) {
ItemsRepository x =new ItemsRepository();
try{
x.findAll(c);
}
catch(Throwable ex)
{
}
You can use the https://junit.org/junit4/javadoc/4.12/org/junit/rules/ExpectedException.html rule.
#Rule
public ExpectedException thrown= ExpectedException.none();
#DataProvider
public Object[][] providedInfo()
{
return new Object[][]
{
{MyGuests1.class,SQLException.class} //and many more
};
}
#Test(dataProvider="providedInfo")
public void f(Class c , Throwable ex) {
thrown.expect(ex);
ItemsRepository x =new ItemsRepository();
x.findAll(c);
}
If there throw is as expected the test case will fail. There is also some more verbose testing options with it.
Additionally you may want to look into assertJ if you are using Java 8 or greater as it has some additional measures for excption testing which may help, but I generally find their API better.
I need to test a constructor which throws an exception using JUnit.
Below is the constructor:
public EISThirdPartyClient(ClientConfiguration _config, String _serviceURL)
throws EISClientException {
super(_config, _serviceURL);
try {
ObjectMapperHolder.initialize(_config);
} catch (Exception e) {
throw new EISClientException(e);
}
}
Below is the test case:
#Test
public void testEISThirdPartyClientConctructor() throws EISClientException {
#SuppressWarnings("unused")
EISThirdPartyClient client = new EISThirdPartyClient(new ClientConfiguration(), "url");
boolean caughtException = false;
try {
ObjectMapperHolder.initialize(null);
} catch (Exception ex) {
if (ex instanceof EISClientException) {
caughtException = true;
assertTrue(ex.getCause() instanceof EISClientException);
} else {
ex.printStackTrace();
fail("Uncaught exception");
}
}
assertTrue(caughtException);
}
I am getting java.lang.AssertionError, which isn't what I'm expecting. Can someone tell me what I am doing wrong?
You're testing the wrong thing - you want to ensure that the construction of your object fails, not that it bails out when ObjectMapperHolder bails out.
You can also greatly simplify the test - you can expect that EISClientException is thrown without needing to do any further validation of the exception.
The main point is to get the test to fail with the minimum required amount of work. It seems that passing null as your configuration might do it, so here's an example with that:
#Test(expected = EISClientException.class)
public void testEISThirdPartyClientConctructor() throws EISClientException {
new EISThirdPartyClient(null, "url");
}
If this doesn't quite suit your needs, you may want to look into a mocking framework like Mockito to provide behavior when you are in the critical section of your code.
I'm trying to run a JUnit test to test a method that will throw an exception. However, the test fails and I have no clue as to why it fails. The method that throws the exception is: calcultor.setN( );. I made two versions of this test, both of them fail even though they should pass.
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testSetNZero() {
exception.expect(IllegalArgumentException.class);
exception.expectMessage("Het aantal CPU's is minder dan 1");
Amdahl calculator = new Amdahl();
calculator.setN(0);
fail("Exception not thrown");
}
#Test (expected = IllegalArgumentException.class)
public void testSetNZero() {
Amdahl calculator = new Amdahl();
calculator.setN(0);
}
Amdahl class:
public class Amdahl
{
private int N;
public void setN (int n) {
if(n < 1) throw new IllegalArgumentException ("Het aantal CPU's is minder dan 1");
this.N = n;
}
}
testSetNZero fails because:
#Test (expected = IllegalArgumentException.class)
public void testSetNZero() {
and
#Rule
public ExpectedException exception = ExpectedException.none();
contradict each other and define a test that will always fail (it must both throw an exception and also not in order to pass). Use either ExpectedException or #Test(expected = ...).
I have solved my issue by using try-catch blocks whenever I expected an exception. If no exception or the wrong exception was present, the test fails.
#Test
public void testSetNZero() {
Amdahl calculator = new Amdahl();
try{
calculator.setN(0);
fail();
} catch(IllegalArgumentException e){}
}
When writing unit tests for a Java API there may be circumstances where you want to perform more detailed validation of an exception. I.e. more than is offered by the #test annotation offered by JUnit.
For example, consider an class that should catch an exception from some other Interface, wrap that exception and throw the wrapped exception. You may want to verify:
The exact method call that throws the wrapped exception.
That the wrapper exception has the original exception as its cause.
The message of the wrapper exception.
The main point here is that you want to be perf additional validation of an exception in a unit test (not a debate about whether you should verify things like the exception message).
What's a good approach for this?
In JUnit 4 it can be easily done using ExpectedException rule.
Here is example from javadocs:
// These tests all pass.
public static class HasExpectedException {
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void throwsNothing() {
// no exception expected, none thrown: passes.
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
thrown.expectMessage(startsWith("What"));
throw new NullPointerException("What happened?");
}
}
As provided in your answer, it's a good approach. In addition to this:
You could wrap the function expectException into a new Annotation, called ExpectedException.
An annotated method would look like this:
#Test
#ExpectedException(class=WrapperException.class, message="Exception Message", causeException)
public void testAnExceptionWrappingFunction() {
//whatever you test
}
This way would be more readable, but it's exactly the same approach.
Another reason is: I like Annotations :)
Looking at the proposed answers, you can really feel the pain of not having closures in Java. IMHO, the most readable solution is ye good old try catch.
#Test
public void test() {
...
...
try {
...
fail("No exception caught :(");
}
catch (RuntimeException ex) {
assertEquals(Whatever.class, ex.getCause().getClass());
assertEquals("Message", ex.getMessage());
}
}
For JUNIT 3.x
public void test(){
boolean thrown = false;
try{
mightThrowEx();
} catch ( Surprise expected ){
thrown = true;
assertEquals( "message", expected.getMessage());
}
assertTrue(thrown );
}
Until this post I've done my exception validation by doing this:
try {
myObject.doThings();
fail("Should've thrown SomeException!");
} catch (SomeException e) {
assertEquals("something", e.getSomething());
}
I spent a few moments thinking about the issue though and came up with the following (Java5, JUnit 3.x):
// Functor interface for exception assertion.
public interface AssertionContainer<T extends Throwable> {
void invoke() throws T;
void validate(T throwable);
Class<T> getType();
}
// Actual assertion method.
public <T extends Throwable> void assertThrowsException(AssertionContainer<T> functor) {
try {
functor.invoke();
fail("Should've thrown "+functor.getType()+"!");
} catch (Throwable exc) {
assertSame("Thrown exception was of the wrong type! Expected "+functor.getClass()+", actual "+exc.getType(),
exc.getClass(), functor.getType());
functor.validate((T) exc);
}
}
// Example implementation for servlet I used to actually test this. It was an inner class, actually.
AssertionContainer<ServletException> functor = new AssertionContainer<ServletException>() {
public void invoke() throws ServletException {
servlet.getRequiredParameter(request, "some_param");
}
public void validate(ServletException e) {
assertEquals("Parameter \"some_param\" wasn't found!", e.getMessage());
}
public Class<ServletException> getType() {
return ServletException.class;
}
}
// And this is how it's used.
assertThrowsException(functor);
Looking at these two I can't decide which one I like more. I guess this is one of those issues where achieving a goal (in my case, the assertion method with functor parameter) isn't worth it in the long run since it's just a lot easier to do those 6+ of code to assert the try..catch block.
Then again, maybe my 10 minute result of problem solving at friday evening just isn't the most intelligent way to do this.
#akuhn:
Even without closures we can get a more readable solution (using catch-exception):
import static com.googlecode.catchexception.CatchException.*;
public void test() {
...
...
catchException(nastyBoy).doNastyStuff();
assertTrue(caughtException() instanceof WhateverException);
assertEquals("Message", caughtException().getMessage());
}
The following helper method (adapted from this blog post) does the trick:
/**
* Run a test body expecting an exception of the
* given class and with the given message.
*
* #param test To be executed and is expected to throw the exception.
* #param expectedException The type of the expected exception.
* #param expectedMessage If not null, should be the message of the expected exception.
* #param expectedCause If not null, should be the same as the cause of the received exception.
*/
public static void expectException(
Runnable test,
Class<? extends Throwable> expectedException,
String expectedMessage,
Throwable expectedCause) {
try {
test.run();
}
catch (Exception ex) {
assertSame(expectedException, ex.getClass());
if (expectedMessage != null) {
assertEquals(expectedMessage, ex.getMessage());
}
if (expectedCause != null) {
assertSame(expectedCause, ex.getCause());
}
return;
}
fail("Didn't find expected exception of type " + expectedException.getName());
}
The test code can then invoke this as follows:
TestHelper.expectException(
new Runnable() {
public void run() {
classInstanceBeingTested.methodThatThrows();
}
},
WrapperException.class,
"Exception Message",
causeException
);
i did something very simple
testBla(){
try {
someFailingMethod()
fail(); //method provided by junit
} catch(Exception e) {
//do nothing
}
}
For JUnit 5 it is much easier:
#Test
void testAppleIsSweetAndRed() throws Exception {
IllegalArgumentException ex = assertThrows(
IllegalArgumentException.class,
() -> testClass.appleIsSweetAndRed("orange", "red", "sweet"));
assertEquals("this is the exception message", ex.getMessage());
assertEquals(NullPointerException.class, ex.getCause().getClass());
}
By returning the exception object itself, assertThrows() allows you to test every aspect regarding your thrown exceptions.
I made a helper similar to the other posted ones:
public class ExpectExceptionsExecutor {
private ExpectExceptionsExecutor() {
}
public static void execute(ExpectExceptionsTemplate e) {
Class<? extends Throwable> aClass = e.getExpectedException();
try {
Method method = ExpectExceptionsTemplate.class.getMethod("doInttemplate");
method.invoke(e);
} catch (NoSuchMethodException e1) {
throw new RuntimeException();
} catch (InvocationTargetException e1) {
Throwable throwable = e1.getTargetException();
if (!aClass.isAssignableFrom(throwable.getClass())) {
// assert false
fail("Exception isn't the one expected");
} else {
assertTrue("Exception captured ", true);
return;
}
;
} catch (IllegalAccessException e1) {
throw new RuntimeException();
}
fail("No exception has been thrown");
}
}
And the template the client should implement
public interface ExpectExceptionsTemplate<T extends Throwable> {
/**
* Specify the type of exception that doInttemplate is expected to throw
* #return
*/
Class<T> getExpectedException();
/**
* Execute risky code inside this method
* TODO specify expected exception using an annotation
*/
public void doInttemplate();
}
And the client code would be something like this:
#Test
public void myTest() throws Exception {
ExpectExceptionsExecutor.execute(new ExpectExceptionsTemplate() {
#Override
public Class getExpectedException() {
return IllegalArgumentException.class;
}
#Override
public void doInttemplate() {
riskyMethod.doSomething(null);
}
});
}
It looks really verbose but if you use an IDE with good autocompletion you will only need to write the type of exception and the actual code under test. (the rest will be done by the IDE :D)