powermockito - testing exception handling - java

Testing a snip:
void somefunction() {
try {
aMock.doSomething();
bMock.another();
} finally {
cMock.cleanup();
}
}
Test:
#Test(expected = Exception.class)
void sometest() {
... setup various mocks ...
PowerMockito.doThrow(new Exception("abc")).when(aMock).doSomething();
outerMock.somefunction();
// ** THIS SHOULD FAIL
verify(bMock).another();
// ** THIS SHOULD FAIL TOO
verify(cMock, never()).cleanup()
}
When I run this it passes. Why? Does the throw Exception (and handling in #Test) trump the verify statements?
If so - is there some way to test that the finally clause was executed?

Because the exception is thrown (for real), everything under your function code is dead code.
outerMock.somefunction(); // throw so, this is the end
// ------- dead code blow:
// ** THIS SHOULD FAIL
verify(bMock).another();
// ** THIS SHOULD FAIL TOO
verify(cMock, never()).cleanup()
So to test the finally block you have to use a normal execution (when no exception occurs). Another solution would be to use a try/catch in the test:
try {
outerMock.somefunction();
fail("was expecting an exception..");
} catch(Exception exception) {
// ignore
}
verify(bMock).another();
verify(cMock, never()).cleanup()
To answer to the question in comments:
assuming the code is now:
void somefunction() {
try {
aMock.doSomething();
bMock.another();
} catch(Exception ex) {
cMock.handleException(ex);
}
}
the test could be:
Exception testEx = new Exception("testing")
Mockito.when(aMock.doSomething()).thenThrow(testEx);
instance.somefunction();
Mockito.verify(cMock).handleException(testEx);

Related

Junit test for catch block not throwing any exception after catching

I have to write Junit test for the catch block. But I am not able to identify what should I assert here. Since the func() is only catching the exception and not throwing anything I cannot assert using Assertions.assertThatExceptionOfType(). I am new to Junit testing so cannot think of anything else. Any possible way to test the type of exception received by catch block.
Method
public void func() {
try {
int x = solve();
} catch(Exception1 e) {
log.warn("error", e);
} catch(Exception2 e) {
log.warn("error", e);
}
}
private int solve() throws ExceptionName {
//do something...
throws new Exception("error occured");
...
}
You can change the visibility of solve() method and test it with all exception cases. For example change it to default
int solve() throws ExceptionName {
Put tests in the same package as class with this method so that it could be access from test.
UPDATE
The best way would be to change the code to be more testable as it was shown above.
In order to not change the code you can use the way from this answer. It can be tricky. With Mockito and PowerMockito you can control when Exception1 or Exception2 are creating. Based on this you will know which catch statement was executed.
In test code it could be like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Exception1.class, Exception2.class, MyClass.class })
public class TestClass {
#Before
public void setup() {
Exception1 cutMock = Mockito.mock(Exception1.class);
PowerMockito.whenNew(Exception1.class)
.withArguments(Matchers.anyString())
.thenReturn(cutMock);
}
#Test
public void testMethod() {
// prepare
MyClasss myClass = new MyClass();
// execute
myClass.func();
// checks if the constructor has been called once and with the expected argument values:
String value = "abc";
PowerMockito.verifyNew(Exception1.class).withArguments(value);
}
}

Mock void method's try catch block and catch exception using EasyMock or Mockito

I have a code something like this and I want to write a unit test to below code, completely . I am able to hit try part of the code but couldn't figure out how I can test the catch exception part.
public class CacheUpdateTask implements Runnable {
private WarehouseCache cache;
private static final int EXPONENTIAL_MULTIPLIER = 100;
private static final int MAXIMUM_TIME_LIMIT = 5;
public CacheUpdateTask(
final WarehouseCache cache) {
this.cache = cache;
}
#Override
public void run() {
LOG.info("Requesting warehouse mapping from AService and updating the cache.");
final Callable<Void> updateCache =
new Callable<Void>() {
#Override
public Void call() throws Exception {
cache.updateWarehouseCountryCodeCache();
return null;
}
};
final Retryer<Void> retryer = RetryerBuilder.<Void>newBuilder()
.retryIfException()
.withWaitStrategy(WaitStrategies.exponentialWait(EXPONENTIAL_MULTIPLIER, MAXIMUM_TIME_LIMIT,
TimeUnit.MINUTES))
.withStopStrategy(StopStrategies.neverStop())
.build();
try {
retryer.call(updateCache); // this is also a void method, so no return here
} catch (ExecutionException | RetryException e) {
e.printStackTrace();
LOG.error(e);
LOG.error("Exception when refreshing the cache.");
}
LOG.info("Cache has been updated.");
}
}
Points to note
Here the retryer is configured to neverStop. Whenever an exception is raised on call retryer.call(updateCache); retryer actually retries. So in try block when retryer.call(updateCache) throws an exception, execution doesn't flow to catch block and just keeps trying.
I tried to mimic code in try block to throw some exception in multiple ways, but it is never invoking the code in catch. Below code is my last attempt before creating this question. In most of my attempts tests are succeeding but I am never ending up testing the catch block
Below code runs successfully, but it is actually not hitting catch block based on code coverage test.
#Test (expected = ExecutionException.class)
public void test_UpdateCacheFOServiceRunException() throws Exception {
WarehouseCacheFOServiceUpdateTask mockUpdateTaskFOService;
WarehouseCache mockClientCache;
mockUpdateTaskFOService = Mockito.mock(WarehouseCacheFOServiceUpdateTask.class);
mockClientCache = Mockito.mock(WarehouseCache.class);
Mockito.doThrow(ExecutionException.class)
.when(mockClientCache).updateWarehouseCountryCodeCacheFOService();
//clientCache.updateWarehouseCountryCodeCacheFOService();
//Mockito.doThrow( ExecutionException.class )
// .when(mockUpdateTaskFOService).run();
mockClientCache.updateWarehouseCountryCodeCacheFOService();
mockUpdateTaskFOService.run();
}
Your test is incorrect to expect this
#Test(expected = ExecutionException.class)
If you look back at your code, you will see that you catch, log and swallow that exception. It is never rethrown, so your test should not expect it.
Other than that, your test looks broadly correct. You have no means to make any meaningful assertions, since the logger is static.
The following is a bit misleading
Mockito.doThrow(ExecutionException.class)
since the ExecutionException you are trying to catch an exception which Retryer is supposed to wrap the original exception with. What you are currently simulating is an ExecutionException wrapping an ExecutionException. It will work for the sake of your test, but is not realistic. I would throw a generic Exception.class (which will then be wrapped).
There is a slight bug in your code which will cause misleading logging. This line will execute even if an exception was thrown, caught, and logged.
LOG.info("Cache has been updated.");
You have two choices, you can either put a return in the catch, or move the logging line.
try {
retryer.call(updateCache);
LOG.info("Cache has been updated."); // this
} catch (ExecutionException | RetryException e) {
e.printStackTrace();
LOG.error(e);
LOG.error("Exception when refreshing the cache.");
return; // or this
}

What if I want to execute identical code when false returned or exception thrown?

My current logic is
try {
Boolean succeeded = process(); /* May throw SpecificException */
if (succeeded) { /* next step */ }
else { /* clean up */ }
} catch (SpecificException e) {
/* clean up */
}
The clean up part is identical. Is there a good solution to avoiding repeating code?
If that try-catch block is a full method (i.e. there's no additional logic that should be executed after that block in the same method), you can write:
try {
Boolean succeeded = process();
if (succeeded) {
/* next step */
...
return;
}
} catch (SpecificException e) {
// don't throw an exception
}
/* clean up */
The particular goal can be achieved by factoring out the clean up code in a method named cleanup() for example and then calling it from else as well as catch block
Alternatively, you can throw an Exception when it is not succeeded, if it makes sense for your code to do so.
try {
Boolean succeeded = process();
if (succeeded) {
//Your code
}
else {
throw new SpecificException(); //or a different custom exception
}
} catch (SpecificException e) {
//Clean up
}
You can also have the logic of process() itself throw a custom Exception upward so you do not need an if-else block at all. This would look like this:
try {
//Process throws a custom ProcessFailureException upwards on a failure
process();
//Your other code
} catch (SpecificException | ProcessFailureException e) {
//Clean up
}
This highly depends if you want your code to throw an exception when something horribly wrong happens.

Test if an exception is caught with Junit

I'll begin with a code example; I have to test a function, which handles data-packets. In this function, the data-packet is opened and when it doesn't contain all expected data, an InvalidParameterExeption is thrown which is logged.
public void handleData(dataPacket) {
try {
analyseData(dataPacket);
} catch (InvalidParameterException e) {
e.printStackTrace()
}
}
So, if everything goes well, my exception is printed in my terminal.
But how can I test this? I can't use this: (because the exception is caught)
#Test(expected = InvalidParameterExeption.class)
public void testIfFaultyDataPacketIsRecognised {
handleData(faultyDataPacket);
}
How can I test that the InvalidParameterExeption is thrown?
You won't catch exceptions that are not thrown. Just test the 'throwing exception' method instead of the 'exception catching' one
#Test(expected = InvalidParameterExeption.class)
public void testIfFaultyDataPacketIsRecognised() {
analyseData(faultyDataPacket);
}
Ideally you should catch and rethrow the exception.But if you dont want to do that then Why not get catch the exception in test case as expected?
#Test
public void testIfFaultyDataPacketIsRecognised () {
try {
handleData(faultyDataPacket);
Assert.fail("Fail! Method was expected to throw an exception because faulty data packet was sent.")
} catch (InvalidParameterException e) {
// expected
}
}

JUnit4 and exception handeling

The following code does not compile, becouse of unreachable catch block.
I want write "tues" function and call it in many other unit test functions.
Is that possible and how to implement that?
private void catchException(boolean condition) {
try
{
assertTrue(condition);
}
catch (SomeException e)
{
fail("exception = " + e.getMessage());
}
}
Thanks!
There is zero need to catch an exception within a test method to fail it:
public Object methodUnderTest() throws SomeException {
...
}
#Test
public void testMethod() throws SomeException() {
Object obj = methodUnderTest();
assert...
}
If SomeException is thrown by methodUnderTest(), testMethod() will fail.
The problem with your code is that assertTrue does not throw SomeException, if you substitute it with the function that does, it will compile.
I'm not entirely sure what you're asking here, but there are a couple things wrong with the code you posted.
You can only have a catch block for a checked exception if the code in the try can potentially throw an exception of the same type you are catching. Since checked exceptions must be declared in the throws clause of a method, you can check to see if any of the methods you are calling throw the exception types you are catching. From the JUnit documentation on assertTrue:
public static void assertTrue(boolean condition)
You can see it doesn't throw any checked exceptions.
Also, calling fail() in a catch block in a JUnit test is not really necessary. A unit test will automatically fail if an uncaught exception is thrown.
Just add throws WhateverException to your test signature and the test will fail if an exception is thrown.
It is actually not really clear what you what to achieve with your code. If you want to have a nicely formatted message in the exception fired by jUnit if your assert fails then consider writing it in this way:
assertTrue("Condition should hold because....", conditionToCheck);
In this way jUnit will print the message you provided if the check fails. I highly recommend this, especially if you have lots of tests because it
helps you to quickly identify the problem
helps your team member to understand the purpose of your assert
Modifying SomeException by Exception will cause the code to compile.
Obviously my question is not clear.
I have many unit tests and all methods are throwing same exception with different error message. "SomeException" is exception I must catch and read error message from it.
What I want to achive is to write one method which will be common to all unit tests and where I could print error message.
Now unit tests looks like this
public void test_something()
{
try
{
assertTrue(bw.doSomething("test"));
}
catch (SomeException e)
{
fail("exception = " + e.getReason());
}
}
public void test_something1()
{
IBroadworks bw = getSomehting1();
try
{
assertTrue(bw.doSomething1("test1"));
}
catch (SomeException e)
{
fail("exception = " + e.getReason());
}
}
...
So below code is repeating in all unit tests and that is not ok.
...
try{
assertTrue(condition);
}
catch (SomeException e)
{
fail("exception = " + e.getReason());
}
...

Categories

Resources