Test fails because of Exception thrown - java

I have this unit test, that the overall test fails because of the exceptions that is thrown, although its expected:
#Test(expected = AutoGenerateStringIdException.class)
public void testPut_shouldThrowException(){
RootEntity rootObject = new RootEntity();
// Some codes here
try {
Key key = store.put(rootObject);
} catch(AutoGenerateStringIdException e){
assertEquals(e.getMessage(), "Cannot auto-generate String #Id");
}
}

You can either have #Test(expected = SomeException.class) or use a try...catch as you're doing. You can't use both of them at the same time.
When you declare a test to expect a certain exception to be thrown and if you catch it within the test, it wouldn't be thrown, would it?
Although I haven't tried it, you could try re-throwing the exception from the catch block.
catch(AutoGenerateStringIdException e){
assertEquals(e.getMessage(), "Cannot auto-generate String #Id");
throw e;
}

Please have a look at the JUnit wiki: https://github.com/junit-team/junit/wiki/Exception-testing It lists different approaches for testing exceptions.

If exception is expected in test, you should not catch it. Just remove try/catch and watch, what happens.

Related

How to cover custom exception when catching an exception in mockito in Java

For eg.
try {
// Some code
}
catch (IOException e) {
throw new CustomDefineException(e);
}
I want to write mockito coverage statement for the catch block. How can that be done? I'm new on mockito framework.
So basically as per Joni, we can only test the catch block, when there is actually an exception that is occurring, till then it cannot be tested.
You can write the test cases that actually make the code to throw exception.
The control would go to the Catch Block and your coverage would increase.
For the test case to pass you can write the test case that would expect to get exception like
#Test(expected = CustomDefineException.class)
public void shouldThrowCustomDefineExceptionWhenWrongParameterIsSupplied() {
// Your Logic to create Exception
}
on the top of the test Method.

JUnit exceptions handling testing

I am trying to test the next exception, but I don't know how to throw the exception from JUnit, because is a internal exception of the method.
public boolean suscribirADato(int idDato) {
InetAddress ip = null;
boolean adecuadamenteSuscrito = false;
try {
ip = InetAddress.getByName(ipMulticast.get(idDato));
grupoMulticast.set(idDato, ip);
conexion.joinGroup(grupoMulticast.get(idDato));
adecuadamenteSuscrito = true;
} catch (IOException e) {
LOGGER.info(e.getMessage());
}
return adecuadamenteSuscrito;
}
Other replied that you should use a mocking framework.
However, my understanding of your question is the following:
I don't know how to throw the exception from JUnit, because is a
internal exception of the method.
What I understand is that you are trying to unit-test an exception thrown and caught inside the method ?
Perhaps your method should be divided into 2 or more methods, which you can test separately ?
From your code sample, the logic being executed when the exception is thrown is
LOGGER.info(e.getMessage());
You may also choose to mock LOGGER and keep a trace when info is called. Then, you can assert that LOGGER.info was indeed called (If I understood correctly, that is).
You need to look into the Mockito framework. http://mockito.org/ when(myMockedObject.routine(anyParameter())).thenThrow(new NullPointerException());

Java-how to use annotation in Junit - eclipse

I am trying to test if a method throws a IllegalArgumentException in Junit with the code below, however it didn't work. Eclipse suggested to create an annotation class, which confuses me a bit. Can I get away without using an annotation? Otherwise what's the best solution for this?
#Test(expected = IllegalArgumentException.class)
public void testRegister(){
myProgram.register(-23); //the argument should be positive
}
I usually try catching the Exception I'm interrested in, and pass the test if it's caught. Try something like this:
try {
myProgram.register(-23);
// (optional) fail test here
}
catch (IllegalArgumentException e){
// pass test here
}
catch (Exception e) {
// (optional) fail test here
}
If you don't want to use an annotation you can catch all exceptions and test in an assertion that the exception is of instance IllegalArgumentException.
Exception e = null;
try {
// statement that should cause exception
} catch(Exception exc) {
e = exc;
}
// Assert that e is not null to make sure an exception was thrown
// Assert that e is of type IllegalARgumentException
But in the end it is much simpler to just use the JUnit annotation. Which seems to be correct to me.

Is it possible to monitor handled exceptions using JUnit?

This is what I have:
#Test
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
Is there any way to mark test as failed if exception has occurred but was handled in catch block in the sendMessage() method?
Thanks
EDIT: It seems like I was too fixated on these legacy tests and how they were used, that totally missed the fact of sendMessage returning a response with a status code (!!!). So now I just assert status codes, can expand these tests into more detailed scenarios and spin them on jenkins. I would like to avoid to answer how these tests were checked previously. The thought to check for status codes came to me after reading Plux's answer. Thanks!
Exactly what you are looking for is not possible with JUnit as far as I know.
If you really would want to test this, you could store some information about the exception in the catch-block where it is handled in the sendMessage() method.
A better option, in my opinion, could be to test the output or state of the object. If the state/output is exactly the same as when an exception doesn't occur, then whats the point of testing it? Do you have an overly broad catch-block?
EDIT: To AdityaTS, I dont have enough reputation to comment on a post, but my comment: you have not supplied all the code, so I can not say for sure, but my guess is that its the Logger.getLogger IN the catch-block that casts the ClassNotFoundException. (Either that or loadConnectionInfo()) see http://docs.oracle.com/javase/7/docs/api/java/lang/ClassNotFoundException.html
You cannot do this without modifying sendMessage method. If for example you catch the exception there but choose to ignore it and just return some value, code outside of the method doesn't know it. You can get around this by refactoring the code of object: move the code that handles the exception to a separate method, called e.g. handleException. Then, in your test you can create a subclass where handleException will execute the original handleException from superclass, but additionally set some flag which you will be able to read in your test and in this way tell that the exception was thrown. However, if you cannot modify the code for object's class, I'm afraid you're out of luck.
So you expect the exception to propagate out of the sendMessage() method, right?
This is another way to write a test that verifies an exception you expect will be thrown.
#Test (expected = MyExpectedException.class)
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
And it's usually best to be as specific as possible (e.g. MyExpectedException.class over Exception.class)
The exception generated in the sendMessage() class will be available in the test method. Add a try catch block around the sendMessage() method like this
#Test
public testSendMessageToStub() {
try
{
object.sendMehssage();
}
catch(Excpetion e) //Use more specific exception type if you know
{
fail(e.getMessage());
}
}
I have tried this in my code. It worked for me. Let me know.
public DBConnectionInfo connectionInit()
{
loadConnectionInfo();
try
{
Class.forName(dbObject.getDriver());
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
try
{
dbObject.setConnection(DriverManager.getConnection(dbObject.getDatabaseURL(), dbObject.getUserName(),
dbObject.getPassword()));
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
return dbObject;
}
The test case for the above class.
#Test
public void testDriverFailure()
{
when(dbModelObject.getDriver()).thenReturn("driver");
when(dbModelObject.getDatabaseURL()).thenReturn("jdbc:postgresql://127.0.0.1:5432/testdb");
when(dbModelObject.getUserName()).thenReturn("postgres");
when(dbModelObject.getPassword()).thenReturn("postgres");
try
{
dbConnector.connectionInit();
} catch (Exception e)
{
assertTrue(e instanceof ClassNotFoundException);
}
verify(dbModelObject).getDriver();
}

is there a way to both catch and throw an exception

I have a method that is going to the DB so all our JDBC stuff in the DAO method is inside a try/catch block. It is catching SQLException
When I write a test case against this method and if a SqlException occurs then my testcase does not say 'caused an error'. it just goes on its merry way.
However, If I dont catch the SqlException in the DAO method but add throws SqlException to the method instead then my test case says 'caused an error' and shows me the error that happened. (this is what I want).
When I try adding throws SqlException along with the method catching the SqlException then also my test case does not say 'caused an error'.
what is the way around it? one is to have try/catch block inside my test case but even if I do this my Junit test case does not say 'caused an error' though the exception IS posted to standard output.
...but besides that anything else?
My IDE is Netbeans. this is where I run the test cases.
Code:
public class MyDaoClass {
Connection con;
public MyDaoClass (Connection connection)
{
this.con = connection;
}
public SomeObject someMethod (String id)
{
try{
Connection con = this.con;
CallableStatement cs = con.prepareCall("{call some_sp_name (?)}");
cs.setString (1, id);
cs.execute()//imagine an error happens here
ResultSet rs = cs.getResultSet()
...
....
//return SomeObject...
}
catch (SqlException e) //If I remove this and add 'throws SQLException to method then everything is ok
{
log.error(e.getMessage());//i dont have access to log object in test case
}
}
}
public class MyTestSuite extends TestCase
{
//populate local connection
public void testSomeMethod () throws SQLException
{
MyDaoClass myd = new MyDaoClass(connection);
SomeObject s = myd.someMethod("blah");
assertEquals (s.getFirstName(), "pepe");
}
}
All checked exceptions in Java must be declared in the method specification. SqlException is a checked exception, so if you want to throw it, you must include it in the specification.
If you want to throw an exception, but you can't change the method specification, you need to use an unchecked exception, like RuntimeException. It will also cause JUnit to show the error that happened.
The Java Tutorials: Exceptions is an excellent reference on this topic.
If you add throws SQLException to the method, then you don't have to try-catch it anymore.
And yes, you can catch and throw an exception:
try {
// some code
}
catch (SomeException e) {
throw e;
// or,
// throw new SomeOtherException();
}
JUnit doesn't care what you write to standard output. If the exception leaks out of your method, then JUnit takes notice.
If you catch the exception inside your method, then it's correct behavior for the exception not to come out of your method, because it was (we hope!) handled there. So a passing test is a Good Thing.
What you should be testing for is whether your method is producing the correct result (whatever that may be) even in circumstances when an exception is thrown (and handled).
that is not the full code is it? the compiler would complain that someMethod is not always returning a value.
If you want to keep the method as is, then at least add "return null;" after the try/catch.
That way, if an SQLException occurs, then assertEquals should throw NullPointerException which should work on your TestCase.
Side advice, i would check if connection is not null before using it.
Instead of re-throwing the exception, you can also return a null reference instead of an empty or incomplete object. Your callers must check for null's and handle the case when the DAO fails to load the object.
Alternatively, you can stub the log object in your JUnit test and inject it into the DAO via an alternative constructor. Your stubbed logger subclass can deliver the message to your test for inspection.
In addition to what Chip Uni said above re: Runtime exceptions to not need to be declared,
you should also note that exceptions can be nested, i.e.
catch (SqlException e)
{
throw new RuntimeException(e);
}
This will throw a RuntimeException that contains an SqlExceotion.

Categories