assertThat error message for unexpected exception - java

I have this sort of JUnit test:
#Test
public void testNullCheck() {
String res = someMethod();
assertThat("This is the someMethodTest", res, is(notNullValue()));
}
If someMethod() throws an exception I get a stack trace but the "This is the someMethodTest" is not printed as assertThat() is not called. Is there a somewhat elegant JUnit/hamcrest way to print a custom error message? Eventually I want this in a parametrized test to print the parameter for which the test fails. Note, I don't want to test for a specific exception.

You could create an own Rule that replaces the exception:
public class NiceExceptions implements TestRule {
public Statement apply(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (AssumptionViolatedException e) {
throw e;
} catch (Throwable t) {
throw new YourNiceException(t);
}
}
};
}
}
public class YourTest {
#Rule
public final TestRule niceExceptions = new NiceExceptions();
#Test
public void yourTest() {
...
}
}

What about this way:
#Test
public void testNullCheck() {
try{
String res = someMethod();
assertThat("This is the someMethodTest", res, is(notNullValue()));
}catch( Exception e /*or any especific exception*/ ){
fail("This is the someMethodTest Error " + e.getMessage() );
}
}

Using Stefan Birkner's suggestion this is what I came up with. Comments welcome.
package my.test;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class ExceptionCatcher implements TestRule {
String msg;
#Override
public Statement apply(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
} catch (AssumptionViolatedException e) {
throw e;
} catch (AssertionError e){
throw e;
} catch (Throwable t) {
msg = t.getMessage() + "; " + msg;
Throwable cause = t.getCause();
if (cause == null)
cause = t;
StackTraceElement[] stackTrace = cause.getStackTrace();
Throwable t1 = null;
try {
t1 = t.getClass().newInstance();
t1 = t.getClass().getDeclaredConstructor(String.class).newInstance(msg);
t1 = t.getClass().getDeclaredConstructor(String.class, Throwable.class).newInstance(msg, t);
t1.setStackTrace(stackTrace);
throw t1;
} catch (Throwable ignore) {
t1.setStackTrace(stackTrace);
throw t1;
}
}
}
};
}
public void setMsg(String msg) {
this.msg = msg;
}
}
And in the test case:
#Rule
public final ExceptionCatcher catcher = new ExceptionCatcher();
#Before
public void setUp() throws Exception {
catcher.setMsg("....");
}
#Test
public void testNullCheck() {
String res = someMethod();
assertThat("This is the someMethodTest", res, is(notNullValue()));
}

Related

Using reflection to identify if the error thrown matches expected error

I need to write a simple code tester program, but I got stuck comparing the given error class with the test expected class. I am supposed to use reflection in this exercise.
I have my code testing class:
public class TestRunner {
private String result = "";
public void runTests(List<String> testClassNames) {
for (String testClassName : testClassNames) {
Class<?> clazz;
try {
clazz = Class.forName(testClassName);
} catch (ClassNotFoundException e) {
throw new IllegalStateException("No such class.");
}
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.getAnnotation(MyTest.class) != null) {
if (testClassName.equals("reflection.tester.ExampleTests1")) {
result += method.getName() + "() - ";
ExampleTests1 instance = new ExampleTests1();
try {
// if null, result = OK
method.invoke(instance);
result += "OK\n";
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
// if error is caught result = FAILED
result += "FAILED\n";
}
} else {
// the second class. should only return "OK" if the error is implemented from the exception class
result += method.getName() + "() - ";
ExampleTests2 instance = new ExampleTests2();
try {
method.invoke(instance);
result += "FAILED\n";
} catch (RuntimeException e) {
Throwable original = e.getCause();
Object expected = method.getReturnType();
if (original.getClass().isAssignableFrom(expected.getClass())) {
result += "OK\n";
} else {
result += "FAILED\n";
}
} catch (InvocationTargetException | IllegalAccessException e) {
result += "ERROR\n";
}
}
}
}
}
}
}
Also have two test classes. In the first one there is only one rule, if the test won't throw an exception the test should pass, and it is working. The second class is more complicated. If the thrown error class is implemented or same to the expected error class then the test should pass and OK should be added to the result. Currently my code won't catch RunTimeException at all and moves to the last catch block. How can I fix this?
I will also add the test class for more information.
public class ExampleTests2 {
#MyTest(expected = RuntimeException.class)
public void test3() {
throw new IllegalStateException();
}
#MyTest(expected = IllegalStateException.class)
public void test4() {
throw new RuntimeException();
}
#MyTest(expected = IllegalStateException.class)
public void test5() {
throw new IllegalStateException();
}
#MyTest(expected = IllegalStateException.class)
public void test6() {
}
public void helperMethod() {
}
}
test3() and test5() should pass, test4() and test6() should fail, helperMethod() won't be checked because I only need to use the tests with #MyTest annotation.
JUnit has an assertThrows method that checks that an Exception is thrown. It has a method signature of
static <T extends Throwable> assertThrows​(Class<T> expectedType, Executable executable){}
Here's the documentation: https://junit.org/junit5/docs/current/api/org.junit.jupiter.api/org/junit/jupiter/api/Assertions.html#assertThrows(java.lang.Class,org.junit.jupiter.api.function.Executable)
and here's how JUnit implements it:
https://github.com/junit-team/junit5/blob/main/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java

Mockito to test the catch block of private method

I need to write a test to verify that when an IOException is thrown by the private method_C, Method_B returns True.
But
public final class A{
public static Boolean Method_B(){
try{
//call a private method C which throws IOException
Method_C
}
catch(final IOException e) {
return Boolean.True
}
}
private static Method_C() throws IOException {
return something;
}
What I tried:
#Test
public void testSomeExceptionOccured() throws IOException {
A Amock = mock(A.class);
doThrow(IOException.class).when(Amock.Method_C(any(),any(),any(),any()));
Boolean x = A.Method_B(some_inputs);
Assert.assertEquals(Boolean.TRUE, x);
}
I am getting compilation errors :
1.Cannot mock a final class
2. Method_C has private access in A
Any suggestions on how this can be rectified?
you are required to use finally in try catch
import java.io.*;
public class Test {
public static Boolean Method_B() {
try {
System.out.println("Main working going..");
File file = new File("./nofile.txt");
FileInputStream fis = new FileInputStream(file);
} catch (IOException e) {
// Exceptiona handling
System.out.println("No file found ");
} catch (Exception e) {
// Exceptiona handling
System.out.println(e);
} finally {
return true;
}
}
public static void main(String args[]) {
if (Test.Method_B()) {
System.out.println("Show true ans");
} else {
System.out.println("Sorry error occure");
}
}
}

Mockito doAnswer()

Can I somehow use doAnswer() when an exception is thrown?
I'm using this in my integration test to get method invocations and the test in configured the #RabbitListenerTest...
#RunWith(SpringRunner.class)
#SpringBootTest
public class MyIT {
#Autowired
private RabbitTemplate rabbitTemplate;
#Autowired
private MyRabbitListener myRabbitListener;
#Autowired
private RabbitListenerTestHarness harness;
#Test
public void testListener() throws InterruptedException {
MyRabbitListener myRabbitListener = this.harness.getSpy("event");
assertNotNull(myRabbitListener);
final String message = "Test Message";
LatchCountDownAndCallRealMethodAnswer answer = new LatchCountDownAndCallRealMethodAnswer(1);
doAnswer(answer).when(myRabbitListener).event(message);
rabbitTemplate.convertAndSend("exchange", "key", message);
assertTrue(answer.getLatch().await(20, TimeUnit.SECONDS));
verify(myRabbitListener).messageReceiver(message);
}
#Configuration
#RabbitListenerTest
public static class Config {
#Bean
public MyRabbitListener myRabbitListener(){
return new MyRabbitListener();
}
}
}
It works ok but when I introduce an Exception being thrown, It doesn't i.e
This works
#RabbitListener(id = "event", queues = "queue-name")
public void event(String message) {
log.info("received message > " + message);
}
This doesn't
#RabbitListener(id = "event", queues = "queue-name")
public void event(String message) {
log.info("received message > " + message);
throw new ImmediateAcknowledgeAmqpException("Invalid message, " + message);
}
Any help appreciated
The LatchCountDownAndCallRealMethodAnswer is very basic
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
invocation.callRealMethod();
this.latch.countDown();
return null;
}
You can copy it to a new class and change it to something like
private volatile Exception exeption;
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
try {
invocation.callRealMethod();
}
catch (RuntimeException e) {
this.exception = e;
throw e;
}
finally {
this.latch.countDown();
}
return null;
}
public Exception getException() {
return this.exception;
}
then
assertTrue(answer.getLatch().await(20, TimeUnit.SECONDS));
assertThat(answer.getException(), isInstanceOf(ImmediateAcknowledgeAmqpException.class));
Please open a github issue; the framework should support this out-of-the-box.

mock a method calling another method using mockito, powermock

-> controller.java
public controller() {
public controller(DataInterpreter interpret,ControllerClientUtility util, InterfaceConnection inter) {
interpreter = interpret;
utility = util;
interfaced = inter;
}
}
...
public void closeOne(String vpnSessionId) throws Exception {
try{
if ( interfaced.connect() && (interfaced.CheckIntegrity(SessionId)) ){
interfaced.kill(vpnSessionId);
}else{
closeAll();
}
}catch(Exception e){
if ( e.getMessage().startsWith("INTERFACE_ERR:") ){
closeAll();
}else{
throw new Exception(e);
}
}
}
-> methods in InterfaceConnection.java
public String getReponseFor(String command) throws Exception{
if (send(command)){
return receive();
}
else{
throw new Exception("INTERFACE_ERR: Could not get Response");
}
}
public List<String> getListOfConnections() throws Exception{
String statusResponse = getReponseFor("something");
..(regex searches and then make a list connectionsConnected)
return connectionsConnected;
}
public boolean CheckIntegrity(String SessionId){
try {
List<String> connections = new ArrayList<String>();
connections = getListOfConnections();
if (connections.contains(SessionId)){
return true;
}
return false;
}catch(Exception e){
return false;
}
}
Is there a way to mock the output of getListOfConnections ? I tried doing something like this but did not work
-> controllerTest.java
#Mock private InterfaceConnection interfaced;
#Before
public void beforeTests() throws Exception {
MockitoAnnotations.initMocks(this);
impl = new Controller(interpreter,utility,interfaced);
...
#Test
public void testDisconnectOneSessionWithBadSessionId_sendCommand() throws Exception{
String badSessionId = "123:123";
List<String> mockConnections = new ArrayList<String>();
mockConnections.add("asdasds");
when(interfaced.getListOfConnections()).thenReturn(mockConnections);
impl.closeOne(badSessionId);
Mockito.verify(utility)....
}
I hope I'm clear, thanks in advance.

Java - How to throw exception outside an anonymous class

try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
});
}
// ...
}
catch(ParseException e)
{
throw AnotherException();
}
// ...
I need to catch thrown exception in the bottom catch, but I cannot overload method via throws construction. How to do with that, please advice? Thanks
Create custom exception, write try catch block in anonymous class and catch it in your catch block.
class CustomException extends Exception
{
//Parameterless Constructor
public CustomException () {}
//Constructor that accepts a message
public CustomException (String message)
{
super(message);
}
}
now
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
try {
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
catch(Exception e){
throw new CustomException();
}
});
}
// ...
}
catch(CustomException e)
{
throw AnotherException();
}
As suggested already, an unchecked exception could be used. Another option is to mutate a final variable. Eg:
final AtomicReference<Exception> exceptionRef = new AtomicReference<>();
SomeInterface anonymous = new SomeInterface() {
public void doStuff() {
try {
doSomethingExceptional();
} catch (Exception e) {
exceptionRef.set(e);
}
}
};
anonymous.doStuff();
if (exceptionRef.get() != null) {
throw exceptionRef.get();
}

Categories