throw checked Exceptions from mocks with Mockito - java

I'm trying to have one of my mocked objects throw a checked Exception when a particular method is called. I'm trying the following.
#Test(expectedExceptions = SomeException.class)
public void throwCheckedException() {
List<String> list = mock(List.class);
when(list.get(0)).thenThrow(new SomeException());
String test = list.get(0);
}
public class SomeException extends Exception {
}
However, that produces the following error.
org.testng.TestException:
Expected exception com.testing.MockitoCheckedExceptions$SomeException but got org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: com.testing.MockitoCheckedExceptions$SomeException
Looking at the Mockito documentation, they only use RuntimeException, is it not possible to throw checked Exceptions from a mock object with Mockito?

Check the Java API for List.
The get(int index) method is declared to throw only the IndexOutOfBoundException which extends RuntimeException.
You are trying to tell Mockito to throw an exception SomeException() that is not valid to be thrown by that particular method call.
To clarify further.
The List interface does not provide for a checked Exception to be thrown from the get(int index) method and that is why Mockito is failing.
When you create the mocked List, Mockito will use the definition of List.class to creates its mock.
The behavior you are specifying with the when(list.get(0)).thenThrow(new SomeException()) doesn't match the method signature in List API, because get(int index) method does not throw SomeException() so Mockito fails.
If you really want to do this, then have Mockito throw a new RuntimeException() or even better throw a new ArrayIndexOutOfBoundsException() since the API specifies that that is the only valid Exception to be thrown.

A workaround is to use a willAnswer() method.
For example the following works (and doesn't throw a MockitoException but actually throws a checked Exception as required here) using BDDMockito:
given(someObj.someMethod(stringArg1)).willAnswer( invocation -> { throw new Exception("abc msg"); });
The equivalent for plain Mockito would to use the doAnswer method

There is the solution with Kotlin :
given(myObject.myCall()).willAnswer {
throw IOException("Ooops")
}
Where given comes from
import org.mockito.BDDMockito.given

Note that in general, Mockito does allow throwing checked exceptions so long as the exception is declared in the message signature. For instance, given
class BarException extends Exception {
// this is a checked exception
}
interface Foo {
Bar frob() throws BarException
}
it's legal to write:
Foo foo = mock(Foo.class);
when(foo.frob()).thenThrow(BarException.class)
However, if you throw a checked exception not declared in the method signature, e.g.
class QuxException extends Exception {
// a different checked exception
}
Foo foo = mock(Foo.class);
when(foo.frob()).thenThrow(QuxException.class)
Mockito will fail at runtime with the somewhat misleading, generic message:
Checked exception is invalid for this method!
Invalid: QuxException
This may lead you to believe that checked exceptions in general are unsupported, but in fact Mockito is only trying to tell you that this checked exception isn't valid for this method.

This works for me in Kotlin:
when(list.get(0)).thenThrow(new ArrayIndexOutOfBoundsException());
Note : Throw any defined exception other than Exception()

Related

Throwing Exception out of annotation

I have an annotation on a method M in which I am making some checks, if the checks doesn't succeed I do not want to execute the underlying method M. I want the caller to know that the call didn't succeed along with the reason.
To achieve this I am throwing an exception out of annotation if checks fails. So here I have a couple of questions:
I am unable to catch the specific exception because the IDE tells me that exception is not being thrown out of the method?
For a quick hack I am catching Exception and then get to the specific Exception by using instance of operator.
Is there any other better way to achieve this?
Do I have a way in which I need not throw the exception?
Annotation aspect code looks something like this:
#Before(value = "#annotation(abc)", argNames = "pjp, abc")
public Object around(ProceedingJoinPoint pjp, ABC abc) throws Throwable {
if(notAllow()){
throw new CustomException("Not allowed");
} else {
pjp.proceed()
}
}
}
The handler code looks something like this:
catch(Exception e){
if(e instanceof CustomException){
// do something
}
}
The IDE can only verify checked exceptions. Make the exception extend RuntimeException.
You can catch that any time you want, because the IDE cannot verify if any code throws it, since methods are not required to declare if they do.

Should I assert or throw an exception in a junit library?

I'm writting a java library to easily write some junit tests. I don't know if I must assert inside my library or throw an exception. Here is an example. Asuming I define, in my library, this function to check the number of methods of class
public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) {
int numberOfMethods = clazz.getDeclaredMethods().length;
//TODO compare number and expected number
}
Should I
Directly assert inside my library
Assert.assertTrue(expectedNumberofMethod > 0);
Assert.assertEquals(numberOfMethods,expectedNumberOfMethods);
//...
Throw an exception an let the user handle this exception. Since this library is designed to be used in unit tests, the user will be able to catch some of this exception using #Test(expected=SomeCustomException.class)
public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) throws IllegalArgumentException, SomeCustomException {
if(expectedNumberOfMethods <= 0)
throw new IllegalArgumentException(/*...*/);
int numberOfMethods = clazz.getDeclaredMethods().length;
if(numberOfMethods != expectedNumberOfMethods)
throw new SomeCustomException(/*...*/);
}
EDIT This is a dummy example
Your are planning to create specialized assert methods, like as you would write an extension to the Assert class.
For this you should directly throw assert errors (variant 1), as the assert methods in Assertdo, providing a helpful error message.
The possibility to specify expected exceptions in the #Test annotation serves a different purpose. With this annotation Junit allows you to test that a piece of code throws an expected exception, without the need in the test code to catch the exception.
I would use the junit fail() method that is used in pretty much all other assert methods in the junit library
public void assertNumberOfMethods(Class clazz, int expectedNumberOfMethods) {
int numberOfMethods = clazz.getDeclaredMethods().length;
if (numberOfMethods != expectedNumberOfMethods) {
fail("some failing message);
}
}
You should throw a java.lang.AssertionError exception if an assertion is false.
Also, try not to re-invent the wheel, take a look at AssertJ which does exactly what you want.
// Example
assertThat(clazz.getDeclaredMethods()).hasSize(5);
expectedNumberofMethod > 0 should be an IllegalArgumentException. The test has not failed, the method has been called incorrectly.
numberOfMethods == expectedNumberOfMethods should throw a java.lang.AssertionError (or a like), how you do this is up to you, you could use Assert.assertThat, but it binds you to a test framework. You could throw it directly, but you have to do more manual work.
If you use Assert.assertThat, remember that the first argument can be a String description of what went wrong. Use it.
Don't use custom exceptions (that do not extent java.lang.AssertionError), think about what the users of your API will be expecting, and do that. Every other assert causes a java.lang.AssertionError to be throw, but you are doing something different.

Java/android: Help understanding this construct, is it a method or anonymous class?

I have been working with a library and I notice the following construct.
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
I am having difficulty in identifying if it is an anonymous class as I don't see it using the interface or concrete class.
Or is it a just a normal method that does a throws IOException.
I am coming from a different programming background and looks kind of strange for me.
Are you forced to use throws ?
If you are asking about the presence of throws IOException, you must declare it using the throws keyword, because it is a checked exception.
So basically
String run (String url) throws IOException { ... }
^ ^ ^ ^
method method param type marks checked ^
return type name and name exceptions the method body
method may throw
Basically, checked exception in Java is any subclass of Throwable which does not inherit from RuntimeException or Error. Whenever your code throws a checked exception, the Java compiler forces you to either catch it or declare it using the throws keyword.
Checked exceptions allow you to verify at compile time that you are either handling exceptions or declaring them to be thrown: When you call a method like run(), the compiler will warn you that you must do something about it (catch or declare). For some explanation why Java enforces this, see e.g. this question on SO.
The article linked above explains what is the semantical difference between checked (e.g. NullPointerException) and unchecked exceptions (e.g. IOException)
Unchecked runtime exceptions represent conditions that, generally speaking, reflect errors in your program's logic and cannot be reasonably recovered from at run time
Checked exceptions represent invalid conditions in areas outside the immediate control of the program (invalid user input, database problems, network outages, absent files)
It is a method.
The signature of the method is String run(String url) throws IOException. It means that the method name is run; that the method take a String as argument; return another String and may throw an IOException.

What is the best runtime exception to use when mandatory input is missing

I have service, a simple class that need to take input and run some business logic. Before executing this service, the user must set all the data. In general, it look like this:
public class TestService extends InnerServiceBase {
/**
* Mandatory input
*/
private Object inputObj;
#Override
protected ErrorCode executeImpl() {
//Some business logic on inputObj
return null;
}
public void setInputObj(Object inputObj) {
this.inputObj = inputObj;
}
}
What is the best runtime exception to throw in case the inputObj is null ?
IllegalStateException seems like the best fit. The object is not in the correct state to have executeImpl() called on it. Whatever exception you use, make sure the error message is helpful.
Whether you should be using an unchecked exception at all is a whole other question...
Depends on the scenario.
If this is part of an API that another developer is using, throwing NullPointerException is reasonable since you don't want that input to be null. Adding a descriptive exception message would be helpful.
If you're not interested in throwing an NPE, or this is part of code that's not going into an API, then you could throw an IllegalArgumentException, as null could be considered an illegal argument.
If setInputObj is called with a null argument, and that's not valid, then throw NullPointerException. There's some debate over the "correct" exception here (IllegalArgumentException or NullPointerException for a null parameter?), but Guava, Apache Commons Lang and even the JDK itself (Objects.requireNonNull) have settled on NPE.
If executeImpl is called before inputObj has been set, throw IllegalStateException.

Handling checked exceptions

I'm reading exception handling in the book "A programmer guide to Java SCJP certificate". The author wrote that :
If a checked exception is thrown in a method, it must be handled in one of three ways:
1.By using a try block and catching the exception in a handler and dealing with it
2.By using a try block and catching the exception in a handler, but throwing
another exception that is either unchecked or declared in its throws clause
3.By explicitly allowing propagation of the exception to its caller by declaring it
in the throws clause of its method header
I understood clearly the first and third, but the second made me a lot of confused. My concerns are that :
-It's still alright even if I don't throw any other unchecked exceptions, so why do we have to throw another exception at here?
-Why do we have to re-declare the exception that we have caught, in throws clause? I think it's over by the handler.
Thanks to everyone.
The book just list three allowed options.
-It's still alright even if I don't throw any other unchecked exceptions,
so why do we have to throw another
exception at here?
You might want to throw another more descriptive exception, for example adding more info.
-Why do we have to re-declare the exception that we have caught, in
throws clause? I think it's over by
the handler.
You don't have to re-declare. But if the new exception you are throwing is checked, then you must declare it in the throws clause. In fact the exception you just caught doesn't need to be declared even if checked.
You may want to do this to catch a checked exception and throw another checked exception of a different kind. Perhaps you want to throw your own exception rather than a different one.
public void doSomething() throws MyCheckedException {
try {
doSomethingThatThrowsSpecificCheckedException();
} catch(SpecificCheckedException e) {
throw new MyCheckedException();
}
}
Or you can throw an unchecked exception (something that is or extends RuntimeException).
public void doSomething() {
try {
doSomethingThatThrowsSpecificCheckedException();
} catch(SpecificCheckedException e) {
throw new RuntimeException();
}
}
First of all, you should declare in the throw clause the exception that you throw, not the one you caught, assuming you are throwing a checked exception.
Second, you don't have to do that. It is just one of the three options.
Why would you do that? Usually this is done between the application layers. For example, Hibernate catches SQLExceptions and rethrows them as unchecked HibernateException, so that code that calls Hibernate methods doesn't have to be polluted with the try/catches for SQLExceptions. Another option is to translate a low-level exception into some business logic exception that can be handled up the stack. This allows for the better isolation of the business logic from the low level implementation details.
Great question, and one which good java programmers should get their head around.
It's all about adhering to the method signature that defines the method's contract with its caller, and which includes what exceptions you are going to throw.
Option 1 is dealing with the exception
Option 2 is not dealing with the exception, but keeping the same contract
Option 3 is not dealing with the exception and changing your contract
A implementation of the pattern in option 2 would be:
public interface Server {
public void useServer() throws ServerException;
}
public class ExplodingClient {
private Server server = new ServerImpl();
public void doIt() throws ClientException {
try {
server.useServer();
} catch (ServerException e) {
// Our contract doesn't allow throwing ServerException,
// so wrap it in an exception we are allowed by contract to throw
throw new ClientException(e);
}
}
}
public class SilentClient {
private Server server = new ServerImpl();
public void doIt() {
try {
server.useServer();
} catch (ServerException e) {
// Our contract doesn't allow throwing any Exceptions,
// so wrap it in a RuntimeException
throw new RuntimeException(e);
}
}
}
By using a try block and catching the
exception in a handler, but throwing
another exception that is either
unchecked or declared in its throws
clause.
Handling the exception in Java can be done in two ways :
Wrapping it in try-catch-finally block.
Declaring the method to throw ( using throws) the exception to the caller of method to handle.
-It's still alright even if I don't throw any other unchecked exceptions,
so why do we have to throw another
exception at here?
Throwing another exception means describing more about it. Also, to let the caller of the method know that this particular exception was generated.
-Why do we have to re-declare the exception that we have caught, in
throws clause? I think it's over by
the handler.
Redeclaring exception that you just caught in the catch block is to make the caller of this method alert that this method could throw a particluar exception. So be prepare to handle it.
You must go over this Jon Skeet's post : Sheer Evil: Rethrowing exceptions in Java
Remember, you are never forced to handle the unchecked exceptions, compiler forces you to just catch the checked one.

Categories