How to force Mockito to throw RemoteException in JUnit test - java

This is my code which I want to force to throw a Remote Exception:
transient Bicycle b=null;
public Bicycle getBicycle() {
if(b==null) {
try {
b=new Bicycle(this);
} catch (RemoteException ex) {
Logger.getLogger(Bicycle()).log(Level.SEVERE, null, ex);
}
}
return b;
}
Here is the JUnit test I am running with Mockito:
boolean exceptionThrown=false;
Bicycle mockB = mock(Bicycle);
mockB.setBicycle(null);
stub(mockB.getBicycle()).toThrow(new RemoteException(){boolean exceptionThrown = true;});
assertTrue(exceptionThrown);
I keep receiving the following error:
Checked exception is invalid for this method!
Any help will be appreciated.
Edit:
Instead of
stub(mockB.getBicycle()).toThrow(new RemoteException(){boolean exceptionThrown = true;});
I have also tried
doThrow(new RemoteException(){boolean exceptionThrown = true;}).when(mockB).getBicycle();
and
Mockito.when(mockB.getBicycle()).thenThrow(new RemoteException(){boolean exceptionThrown=true;});
Still no luck.
Edit2 - gone one step further after fully understanding the API and using it correctly:
when(mockB.getBicycle()).thenThrow(new RuntimeException());
I don't know how to make the assert now. I tried putting a boolean once the exception gets called but the assert cannot see the boolean.
Any ideas?

The getBicycle() method will never return a RuntimeException. The code itself is catching the RuntimeException and, when caught, writes to the logger. The method itself will either return the Bicycle or null.
You will need to rethink how you want the getBicycle method operates. It could re-throw the RuntimeException atfer logging if you want the RuntimeException to bubble through. But, based on how that's written, the RuntmeException will never make it out to the JUnit test

Related

How do I avoid getting "Missing return statement" when calling a method that throws an exception, from within another method?

I have a method that handles different error codes and always throws unchecked exception. This method is used in many places across the class. When I try to call it inside another method that has not void return type as shown below:
public Object someMethod() {
....
if(success){
return result;
} else {
callMethodThatAlwaysThrowsUncheckedExceptions();
}
}
java compiler says that the method is missing return statement.
Only two options come to my mind how to solve this problem:
replace method call with its content
add a return statement just after method call that returns an empty object
However I don't really like any of these options: the first one because of code duplication and the second one because of the need to write code that will never be executed.
Is there any other way to solve this problem?
Just swap around the terms, you'll never get to return if the method throws.
if(!success){
callMethodThatAlwaysThrowsUncheckedExceptions();
}
return result;
Or even
callMethodThatAlwaysThrowsUncheckedExceptions(succes);
return result;
Just check the success condition in your throwing method.
Next to the great answer already provided by Slawomir Chodnicki, here's another suggestion.
Change your callMethodThatAlwaysThrowsUncheckedExceptions() which somewhere throws an Exception into a factory method. E.g: change this:
// somewhere in callMethodThatAlwaysThrowsUncheckedExceptions
throw new MyException();
To:
return new MyException();
That way you can call that method like this:
throw callMethodThatAlwaysThrowsUncheckedExceptions();
And thus will help the compiler to see that this is the last statement of that execution branch.
This also works greatly with different exceptions, just return instead of throw
To indicate that you don't expect a line to be reachable (after your call to the throwing method) you can
throw new AssertionError("comment to your co-developers why this never gets reached")
I like minus's answer, but it can be a bit unreadable to users that might mistakenly think return result; will always be executed (regardless of the value of success).
As an alternative, you can change
void callMethodThatAlwaysThrowsUncheckedExceptions () {}
to
Object callMethodThatAlwaysThrowsUncheckedExceptions () {}
(no need to change the method body).
Now you can write
public Object someMethod() {
....
if (success) {
return result;
} else {
return callMethodThatAlwaysThrowsUncheckedExceptions();
}
}
None of the answers above matched my taste of programming. The closest match that I found is here. Inspired from this linked answer, I handled such missing return statement errors in the following way:
First making the return type of the method same as that of exception which it always throws
MyCustomRuntimeException callMethodThatAlwaysThrowsUncheckedExceptions() {
// ....
throw new MyCustomRuntimeException();
}
Next whenever we have to fail the method execution, simply call above method and throw it
public Object someMethod() {
// ....
if (success) {
return result;
} else {
throw callMethodThatAlwaysThrowsUncheckedExceptions();
}
}
This can be used even in methods having void return type without explicitly mentioning the throw keyword. Ofcourse in such places some IDEs may warn of UnusedReturnValue but that can be suppressed as well.

How to make java compiler ignore errors/warnings

So I have the following bit of code:
public static Image getImage(String filepath, Class cl) {
try {
return ImageIO.read(cl.getResource(filepath));
}
catch (IOException e) {
e.printStackTrace();
}
return null; // Will never execute
}
It's a basic try-catch block. If I am unable to read the image and return it, I immediately go into my catch block. However, because my return is within the scope of the try block and not the entire function, my compiler issues an error when I try to compile and run because it sees that it's possible that I never hit a return statement. Therefore, I've added the return null; line to suppress this warning, but I'd rather have a neater way of doing this without putting code that will never run. I've tried adding
#SuppressWarnings("all")
To my code, but it still gives me an error. Any ideas? I feel like there should be a way to tell the compiler to ignore errors like this.
Also, if it is of any use, I am using IntelliJ as my IDE.
I would suggest what #LuCio eagerly in the comments tried to say. Just don't catch the Exception and pass it upwards:
public static Image getImage(String filePath, Class<?> clazz) throws IOException {
return ImageIO.read(clazz.getResource(filePath));
}
That way you have created an easy helper method. If you would return null, you'd have to document that in JavaDoc and every caller will have to use a not-null assertion logic to then throw an error if it is null.
A try catch block does the same. So instead of passing null upwards you just propagate the exception upwards. You somewhere said that you want to assign the Image to a static field, so you can do that easily like this:
static {
try {
MY_IMAGE = getImage("somepath", MyClass.class);
} catch(IOException e){
throw new IOError(e); // will kill the Vm with an error
}
}
But maybe somewhere you have another action. Than to just kill the VM. Maybe use a default image:
final Image image;
try {
image = getImage("somepath", MyClass.class);
} catch(IOException e){
e.printStacktrace();
image = new SomeDefaultImage();
}
// do something with image
Which all in all is the way to go. You can't have a helper method to decide what to do when it fails. That should always be done by the calling code.
Ok so, I believe I was confusing the purpose of the catch block. Thank you to #Ben and #Zephyr and everybody else for your help. I will be amending my code to:
public static Image getImage(String filepath, Class cl) {
try {
return ImageIO.read(cl.getResource("hello"));
} catch (IOException e) {
System.out.println(e.getMessage());
e.printStackTrace();
throw new IOError(e);
}
}
Edit: After some more discussions, and looking through other options other people have posted, I have updated my code above, which satisfies the compiler. Note that replacing the line
throw new IOError(e)
with
System.exit(0);
does not fix the error because, as far as I know, the compiler cannot tell at compile time whether the program would end. It would've been helpful to have a way of suppressing the warning, since we know that at runtime the program will always (or practically always) end, but alas #SuppressWarnings is of no use.

checked exception is invalid for this method [duplicate]

This question already has answers here:
throw checked Exceptions from mocks with Mockito
(5 answers)
Closed 5 years ago.
I have the below class
There is an answer to this in StackOverflow but it deals with List throw checked Exceptions from mocks with Mockito. I like to look into this condition. Not getting where I am missing.
public SimpleClass{
private SimpleClass() {}
public void runMethod(request,String,Map,Object,Object) {
try {
doesSomething()....
}
}
catch(Exception e) {
String message = "" + request.getAttribute(X) + "Some message";
Logger.Log(param1 + param2 + message);
}
}
My Test method looks like below. I trying to run the coverage with the JUnit but the Catch Block is not covered, so Wrote the below test method. It throws the below exception. Not able to get where I am missing.
public class SimpleClassTest{
#Test
public void testCatchBlock() {
SimpleClass instanceObj = PowerMockito.mock(SimpleClass.class);
Mockito.doThrow(new Exception())
.when(instanceObj)
.runMethod(request, anyString(), anyMap(), anyObject(), anyObject());
}
}
Exception Thrown
org.mockito.exceptions.base.MockitoException:
Checked exception is invalid for this method!
Invalid: java.lang.Exception
Edit
I am able to run the method by giving NullPointerException. When I try for code coverage with Junit, the catch block is completely shown as red, and the catch phrase is shown yellow. How do I achieve 100% coverage and how to test the String message in the catch block.
You are getting unit testing with mocking wrong. Here:
SimpleClass instanceObj =PowerMockito.mock(SimpleClass.class);
There is no point in mocking the class that is under test!
When you mock that class, you get a stub that has "nothing to do" with your real implementation. A "working setup" would look more like:
public void methodUnderTest(X x, ...) {
try {
x.foo();
} catch (Exception e) {
...
}
and
X mockedX = mock(X.class);
when(x.foo()).thenThrow(new WhateverException());
underTest.methodUnderTest(mockedX); ...
and then you could try to verify for example that the logger saw that expected logging call. In other words: you either use a mock to allow your code under test to do its job (with you being in control!) or to verify that some expected call took place on a mock object.
But as said: it doesn't make any sense to mock that class that you want to test. Because a mocked object doesn't know anything about the "real" implementation!
Manipulate the environment so that doesSomething() throws the Exception you want. Since we do not know what doesSomething() really does, one cannot say more.

Chained Exceptions initCause(), is this correct?

I have a method:
public void SomeDataMethod() throws BadDataException {
try {
// do something
} catch(IOException e) {
throw new BadDataException("Bad data",e);
} finally {
// do something regardless of above
}
}
And now for example some code will invoke this method, and I want to see all failures which happened in this method,
so how can I do it by using initCause()? Or maybe is there any other way to do this? And if I use initCause():
1) will I get all exceptions which were catch or the last one?
2) and What form do I get them / it?**
When you call an Excepion Constructor with the throwable attached, like you have the e as part of the new BadDataException("Bad data",e); then the result is effectively the same as:
BadDataException bde = new BadDataException("Bad data");
bde.initCause(e);
This is to keep compatibility with earlier Java versions which did not have the initCause concept.
Not all exceptions support adding the cause as part of the constructor, and for those exceptions you can initCause it.
note that you can only initCause an exception once, and initializing it with 'null' cannot later be changed:
BadDataException bde = new BadDataException("Bad data", null);
// this will fail.....
bde.initCause(e);
To get the cause of an exception, you call... getCause(). In this case, this method will return the IOException that you wrapped inside your BadDataException. It can't return more that one exception, since you can only wrap one exception.

Testing for multiple exceptions with JUnit 4 annotations

Is it possible to test for multiple exceptions in a single JUnit unit test? I know for a single exception one can use, for example
#Test(expected=IllegalStateException.class)
Now, if I want to test for another exception (say, NullPointerException), can this be done in the same annotation, a different annotation or do I need to write another unit test completely?
You really want the test to do one thing, and to test for that. If you're not sure as to which exception is going to be thrown, that doesn't sound like a good test to me.
e.g. (in pseudo-code)
try {
badOperation();
/// looks like we succeeded. Not good! Fail the test
fail();
}
catch (ExpectedException e) {
// that's fine
}
catch (UnexpectedException e) {
// that's NOT fine. Fail the test
}
so if you want to test that your method throws 2 different exceptions (for 2 sets of inputs), then you'll need 2 tests.
This is not possible with the annotation.
With JUnit 4.7 you can use the new ExpectedException rule
public static class HasExpectedException {
#Interceptor
public ExpectedException thrown= new ExpectedException();
#Test
public void throwsNothing() {
}
#Test
public void throwsNullPointerException() {
thrown.expect(NullPointerException.class);
throw new NullPointerException();
}
#Test
public void throwsNullPointerExceptionWithMessage() {
thrown.expect(NullPointerException.class);
thrown.expectMessage("happened?");
throw new NullPointerException("What happened?");
}
}
More see
JUnit 4.7: Interceptors: expected exceptions
Rules in JUnit 4.7
If updating to JUnit 4.7 is not possible for you, you have to write a bare unit test of the form
public test() {
try {
methodCall(); // should throw Exception
fail();
}
catch (Exception ex) {
assert((ex instanceof A) || (ex instanceof B) || ...etc...);
...
}
}
Although this is not possible with JUnit 4, it is possible if you switch to TestNG, which allows you to write
#Test(expectedExceptions = {IllegalArgumentException.class, NullPointerException.class})
Use catch-exception:
// test
public void testDo() {
// obj.do(1) must throw either A or B
catchException(obj).do(1);
assert caughtException() instanceof A
|| caughtException() instanceof B;
// obj.do(2) must throw A but not SubclassOfA
catchException(obj).do(2);
assert caughtException() instanceof A
&& !(caughtException() instanceof SubclassOfA);
}
#Test(expected=Exception.class)
This will throw all possible exceptions.
How would you expect to "expected"s to work? A method can only throw one exception.
You would have to write a different unit test for each way the method can fail. So if the method legitimately throw two exceptions then you need two tests set up to force the method of throwing each exception.
Keep the tests as simple and short as possible. The intention of a JUnit-Test is to test only one simple functionality or one single way of failure.
Indeed, to be safe, you should create at least one test for every possible execution way.
Normally, this is not always possible because if you have a method that analyses a string, there are so many possible string combinations that you cannot cover everything.
Keep it short and simple.
You can have 30-40 testing methods for one single method easily... does it really matter?
Regards

Categories

Resources