Issues trying throw checked exception with mockito - java

I have the below interface
public interface Interface1 {
Object Execute(String commandToExecute) throws Exception;
}
which then I 'm trying to mock so I can test the behaviour of the class that will call it:
Interface1 interfaceMocked = mock(Interface1.class);
when(interfaceMocked.Execute(anyString())).thenThrow(new Exception());
Interface2 objectToTest = new ClassOfInterface2(interfaceMocked);
retrievePrintersMetaData.Retrieve();
But the compiler tells me that there is an unhandled exception.
The definition of the Retrieve method is:
public List<SomeClass> Retrieve() {
try {
interface1Object.Execute("");
}
catch (Exception exception) {
return new ArrayList<SomeClass>();
}
}
The mockito documentation only shows uses of RuntimeException, and I have not seen anything on similar on StackOverflow.
I'm using Java 1.7u25 and mockito 1.9.5

Assuming your test method doesn't declare that it throws Exception, the compiler's absolutely right. This line:
when(interfaceMocked.Execute(anyString())).thenThrow(new Exception());
... calls Execute on an instance of Interface1. That can throw Exception, so you either need to catch it or declare that your method throws it.
I would personally recommend just declaring that the test method throws Exception. Nothing else will care about that declaration, and you really don't want to catch it.

You can use doAnswer method of Mockito to thrown checked exceptions, like this
Mockito.doAnswer(
invocation -> {
throw new Exception("It's not bad, it's good");
})
.when(interfaceMocked)
.Execute(org.mockito.ArgumentMatchers.anyString());

You shouldn't be having a problem if your method returns something and throws your error. Now if your method returns void you won't be able to throw an error.
Now the real thing is that you're not testing that your interface throws an exception, instead what you're testing what happens when an exception is thrown within this method.
public List<SomeClass> Retrieve() {
try {
interface1Object.Execute("");
}
catch (Exception exception) {
return handleException(exception);
}
}
protected List<SomeClass> handleException(Exception exception) {
return new ArrayList<SomeClass>();
}
Then you just call your handleException method and make sure it returns the correct thing. If you need to make sure that your interface is throwing an exception, then that is a different test for your interface class.
It might seem sucky that you are having to make a method for a single line but that's what happens sometimes if you want testable code.

Related

Mockito chained method calls relying on previous call not recognized

I am using Mockito services to test the Exception that could be thrown in MyFinalClass2 and be caught in MyAbstractClass as the concrete method makes a call to the getValue method in MyFinalClass2. This method returns an interface (MyInterfaceClass) object.
I asked a question earlier in Mocking Chained calls in Concrete Class Mockito and thankfully, the solution provided works when calling the getObject method found in MyFinalClass . Therefore, test1 works!
However, this time I have another final class (MyFinalClass2) which is not #Autowired, and is called after a call to a method in MyFinalClass. An Object of type MyFinalClass2 is return from the first call to method in MyFinalClass. When manually throwing a MyException2 in test2 , it does not get recognized and therefore causes an AssertionFailure in Test2 .
Also please note, the below line of code returns NULL as it has not yet been implemented. Which is the reason why I am returning in Test2 a new instance of MyFinalClass2 when this method is called.
MyFinalClass2 myFinalClass2 = getObject(strName);
Please see below code.
public abstract class MyAbstractClass{
#Autowired
private MyFinalClass myFinalClass;
//concrete method
protected MyInterfaceClass myConcreteMethod(String strName, String str)
{
try{
//returns null as it has not yet been implemented
MyFinalClass2 myFinalClass2 = getObject(strName);
MyInterfaceClass b = getValue(myFinalClass2,str);
return b;
} catch(MyException e){
LOGGER.log("ERROR THROWN" + e);
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
}
}
public MyFinalClass2 getObject(String strName){
return myFinalClass.getObject(strName);
}
public MyInterfaceClass getValue(MyFinalClass2 myFinalClass2, String
str){
return myFinalClass2.getValue(str);
}
}
public final class MyFinalClass {
public MyFinalClass2 getObject(String strName) throws MyException{
**** HAS NOT YET BEEN IMPLEMENTED ****
return null;
}
}
public final class MyFinalClass2 {
public MyInterfaceClass getValue(String str) throws MyException2{
**** HAS NOT YET BEEN IMPLEMENTED ****
return null;
}
}
public interface MyInterfaceClass {
**** HAS NOT YET BEEN IMPLEMENTED BY ANY CLASS ****
void getStuff();
}
#ContextConfiguration(locations = "classpath:applicationContext-test.xml")
#RunWith(PowerMockRunner.class)
public class MyAbstractClassTest {
public static class ExampleConcreteClass extends MyAbstractClass{
}
#InjectMocks
#Spy
ExampleConcreteClass exampleConcreteClass;
#Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
//THIS WORKS --- TEST 1
#Test
public void testIfExceptionOneIsThrown(){
try{
Mockito.when(exampleConcreteClass).getObject(name).
thenThrow(new MyException());
exampleConcreteClass.myConcreteMethod();
Assert.fail();
}catch(MyException e){
Assert.assertTrue(Boolean.TRUE);
}
}
//This test DOES NOT work --- TEST 2
#Test
public void testIfExceptionTwoIsThrown(){
try{
MyFinalClass2 myFinClass2 = new MyFinalClass2();
String strName = "name";
String str = "str";
Mockito.when(exampleConcreteClass).getValue(myFinClass2,str).
thenThrow(new MyException2());
Mockito.when(exampleConcreteClass).getObject(strName).
thenReturn(myFinClass2);
exampleConcreteClass.myConcreteMethod();
Assert.fail();
}catch(MyException e){
Assert.fail();
}catch(MyException2 e){
Assert.assertTrue(Boolean.TRUE);
}
}
}
Please help. Greatly Appreciated!
First of all, I am sorry to say so, but if you need to think that hard about testing, it's normally a sure sign that the code is bad. Anway, you don't need PowerMock there, since Mockito 2 is able to mock final classes already (you have to opt-in for that, though).
Also your test doesn't make any sense at all, since your exampleConcreteClass.myConcreteMethod() cannot throw a MyException2, because...
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
}
...thus the MyException2 will never leave the scope of the method, but be transformed into a log message there and then be discarded. It will not leave the method, thus trying to assert it will not work. You would have something like throw e; there, too:
} catch(MyException2 e){
LOGGER.log("ERROR THROWN" + e);
throw e; // re-throw e, otherwise it ends here
}
Also, just as a hint, what you are trying to do there can be more easily done by simple writing...
#Test(expected=MyException2.class)
public void testIfExceptionTwoIsThrown() throws MyException, MyException2 {
...this way, you can remove all the try-catch stuff from your test method, since JUnit will automatically fail the test if no MyException2 is thrown. Alternatively, if you want to have more control, you can even have a look at JUnit's ExpectedException rule, which is a little bit more powerful and versatile than just the expected parameter (but that one should be enough for this case).
But of course, nothing changes the fact that, as long as your method catches your MyException2, it will not leave said method, so testing for it will not help.

Widening exception of overridden method in Java

Assume we have two classes:
Class A:
import java.io.IOException;
public class A {
public void test() throws IOException{
System.out.println("test in A");
}
}
Class B:
import java.io.IOException;
public class B extends A {
#Override
public void test() throws Exception{
System.out.println("test in B");
}
}
This gives a compiler error, and I would like to know the reason for it. I can get the answer by myself, but this is not fully scientific, but partly logically.
I wrote a blog post in Azerbaijani. When I wrote the blog I was stuck in the loading process.
Please be careful in quotes:
I think that when the compiler reads the B class, it loads the method headers of A and method headers of B. And when you call test of A, the JVM calls the test of A, but as body calls test of B, and at that time we will have this method:
public void test() throws IOException{ // <-- Header of A
System.out.println("test in B"); // <-- Body of B
// Here I can throw wide Exception from IOException
// because here is the body of the test in B. The test
// method in B can throw Exception so the compiler
// doesn't approve of this version of the code.
}
Is the process really going on as what I wrote above?
Loading headers issue I was stuck exactly here.
How does the linking process work? I can't figure out background of
A a = new B(); // When the compiler converts this line into bytecode
// does it loads of method headers of A and method
// body's of B
a.test()
calls the test of the B class. I know logically, but I can't figure out at the compiler level, linking process.
Imaigine you have the following code:
A a = new B();
try {
a.test();
} catch (IOExceoption e) {
//do some specific handle for IOExceoption
}
Now imaigine what happens if b.test() throw an Exception which is NOT IOException? nobody will handle it, and that breaks java's checked exceptions mechanism.
The other way around however, is perfectly fine:
public class A {
public void test() throws Exception {
System.out.println("test in A");
}
}
public class B extends A {
#Override
public void test() throws IOException{
System.out.println("test in B");
}
}
A a = new B();
try {
a.test();
} catch (Exception e) {
//handle
}
Now, note that the catch handles a general Exception, including the specific IOException, and the code will compile perfectly.
The overidden method can throw anything which is an IOException your case. Or more generally, it can throw any exception that is a ParentException. So, you can throw FileNotFoundException since it is also an IOException.
Why?
Not adhereing to this rule breaks the primary contract between parent-child in inheritance.
Somewhere else in your code you can safely assume that the exception thrown from the call to test() will always be IOException irrespective of Which implementation of A threw it. If you were allowed to throw InterruptedException in your case, what exception should the caller catch?
The compiler doesn't load anything. It just marks the method as invoke virtual which means this method is overriden and supposed to be called at run-time based on the object type
From a bit different angle, you are basically not overriding existing method in super type.
Exceptions which are thrown are part of the method's signature.
When you declare your test method in class B with override annotation, you are in fact trying to override (or implement) method which does not exist in its parent A.

EasyMock partial mock private methods

I have the following scenario:
public class ClassA {
public void methodA(){
try {
int result=methodB();
} catch (IOException e) {
//Some code here
}
}
private int methodB() throws IOException{
//Some code here
return 1;
}
}
I want to cover the catch block of the public method methodA() in my test. I don't want to change the visibility of the private method. Is there any way to achieve partial mock of private method using EasyMock? Or is there any way to change the behaviour of private method in my Junit class to throw exception without using mocking?
Thanks in advance.
You cannot do this with Easymock alone, you can do this with a combination of EasyMock and Powermock. Then you mock the return value of the private method.
To test the catch block, you must tell EasyMock to throw an exception when calling methodB.
From the docs:
For specifying exceptions (more exactly: Throwables) to be thrown, the object returned
by expectLastCall() and expect(T value) provides the method andThrow(Throwable throwable).
The method has to be called in record state after the call to the Mock Object for which
it specifies the Throwable to be thrown.
Example:
expectLastCall().andThrow(new IOException("Now to test catch block..."));

High Level Overview Of Throwing Exceptions In Java

I am a little bit confused with exceptions in Java and when to use which particular style of implementation.
I used IllegalArgumentException as an example, but the main point I would like to address is when does one throw, extends or throw new exception?
Also as an additional point I have an assignment where I have to create a java class and the spec vaguely states that the constructor should throw an IllegalArgumentException so which one would be the best to use?
public class Test{
//when does one use this type of exception
public Test(String yourName) throws IllegalArgumentException{
//code implemented
}
//when does one use this type of exception
public Test(String yourName) extends IllegalArgumentException{
//code implemented
}
public Test(String yourName){
if(yourName.length() <= 0){
//why not use this type of exception instead
//and what happens when I use this type of exception
throw new IllegalArgumentException("Please Enter Your Name..!");
}
}
}
Thanks in advance.
When some Exception occurs, you have two ways of handling it: doing throws from the method or doing try-catch. The first one looks like this:
public class MyClass {
public void myMethod() throws IllegalArgumentException {
someOtherMethod();
}
}
In this case you know that someOtherMethod() can throw an exception and you don't want to handle it - you just pass it further. After that, the invoker of myMethod() should take care of the Exception.
But the second way is when you handle it by yourself:
public void myMethod() {
try {
someOtherMethod();
} catch (Exception e) {
System.out.println("You've got an exception!");
}
}
About throwing exceptions manually - you may suppose that you do it in someOtherMethod(). When you do throw new IllegalArgumentException("Please Enter Your Name..!"); the program stops with a message about this exception (unless you handle it in a try-catch way).
And at last, you extend some exception, when you create your own Exception class:
class MyException extends IllegalArgumentException {
...
}
In this case you may do throw new MyException(); in your code.
I'd advise you to read more about exceptions in Java to understand what is going on. You may start with this lesson.
To ensure that you don't end up creating exceptions which already have equivalent in the standard library, I normally have a peek at the documentation before creating new exceptions. Also, it's very easy to go crazy with really big exception hierarchies if you are not careful. Don't create new exceptions just because you think you need to throw one somehow; create one because a code somewhere down the call stack would be doing something useful/different with that exception.
public Test(String yourName) throws IllegalArgumentException
You normally never specify runtime exception in the throws clause though it might be helpful if you need this information to be part of the public API.
public Test(String yourName) extends IllegalArgumentException
This doesn't look right and isn't valid Java.
I would only create a new exception type when you need to. You need a new type when you expect the caller to have catch clause for your new exception.
you can create new exceptions just to be more descriptive but that is what I use the message for.

Delay EasyMock verification

I'm using EasyMock to create mock objects for JUnit testing in Java. I create a mock object and pass it to another thread where it expects methods to be called. In the other thread, the calls are enclosed in a try/catch(Throwable) block, so when an unexpected call occurs on the mock and it thus throws AssertionError, that error is caught by the catch block and treated. So, even though an unexpected call occurred, the test passes.
In order to have the test fail as expected, I would like to delay all verification of calls to the EasyMock.verify(mock) call made in the test-runner thread at the end. Is this possible and how?
I'm not sure about how to do this with EasyMock, but this behavior is possible with Mockito because verification assertions can be specified at the end of the test.
The correct solution I'd guess is to stop catching Throwable. Doing so catches all Errors as you're finding, which can be quite dangerous... are you absolutely positively 100% sure you need to catch Throwable? Why?
(If it turns out you do, you could catch AssertionError specifically and rethrow it. But that's ugly!)
Try using nice mocks:
http://easymock.org/EasyMock2_5_2_Documentation.html
"Nice Mocks
On a Mock Object returned by createMock() the default behavior for all methods is to throw an AssertionError for all unexpected method calls. If you would like a "nice" Mock Object that by default allows all method calls and returns appropriate empty values (0, null or false), use createNiceMock() instead. "
Default values will be returned for unexpected calls instead of throwing AssertionError, but you can still verify them with the verify() method (in which case the AssertionErrors will be thrown)
As #deterb suggested, it's possible with Mockito but you have to know the method name or you have to set expectations for every method. Here is an example:
The mocked interface:
public interface MyInterface {
void allowedMethod();
void disallowedMethod();
}
The user class which catches AssertionError:
public class UserClass {
public UserClass() {
}
public static void throwableCatcher(final MyInterface myInterface) {
try {
myInterface.allowedMethod();
myInterface.disallowedMethod();
} catch (final Throwable t) {
System.out.println("Catched throwable: " + t.getMessage());
}
}
}
And the Mockito test:
#Test
public void testMockito() throws Exception {
final MyInterface myInterface = mock(MyInterface.class);
UserClass.throwableCatcher(myInterface);
verify(myInterface, never()).disallowedMethod(); // fails here
}
The same is possible with EasyMock but it needs some work:
#Test
public void testEasyMock() throws Exception {
final AtomicBoolean called = new AtomicBoolean();
final MyInterface myInterface = createMock(MyInterface.class);
myInterface.allowedMethod();
myInterface.disallowedMethod();
final IAnswer<? extends Object> answer = new IAnswer<Object>() {
#Override
public Object answer() throws Throwable {
System.out.println("answer");
called.set(true);
throw new AssertionError("should not call");
}
};
expectLastCall().andAnswer(answer).anyTimes();
replay(myInterface);
UserClass.throwableCatcher(myInterface);
verify(myInterface);
assertFalse("called", called.get()); // fails here
}
Unfortunately you also have to know the method names here and you have to define expectations like myInterface.disallowedMethod() and expectLastCall().andAnswer(answer).anyTimes().
Another possibility is creating a proxy with the Proxy class (with a custom InvocationHandler) and using it as a mock object. It definitely needs more work but it could be the most customizable solution.
Finally don't forget that it's also possible to create a custom implementation with or without delegation to the EasyMock mock object. Here is one with delegation:
public class MockedMyInterface implements MyInterface {
private final MyInterface delegate;
private final AtomicBoolean called = new AtomicBoolean();
public MockedMyInterface(final MyInterface delegate) {
this.delegate = delegate;
}
#Override
public void allowedMethod() {
delegate.allowedMethod();
}
#Override
public void disallowedMethod() {
called.set(true);
throw new AssertionError("should not call");
}
public boolean isCalled() {
return called.get();
}
}
And the test for it:
#Test
public void testEasyMockWithCustomClass() throws Exception {
final MyInterface myInterface = createMock(MyInterface.class);
myInterface.allowedMethod();
final MockedMyInterface mockedMyInterface =
new MockedMyInterface(myInterface);
replay(myInterface);
UserClass.throwableCatcher(mockedMyInterface);
verify(myInterface);
assertFalse("called", mockedMyInterface.isCalled()); // fails here
}

Categories

Resources