JUnit testing custom exception [duplicate] - java

This question already has an answer here:
Junit Test Case for exception [closed]
(1 answer)
Closed 7 years ago.
I'm using JUnit and not quite sure how to test custom exception class. I have created,
public class CustomException extends Exception {
//#param message is the exception message
public CustomException(final String message) {
super(message);
}
//#param message is the exception message
//#param cause is the cause of the original exception
public CustomException(final String message, final Throwable cause) {
super(message, cause);
}
}
main class would have many try catch such as:
catch (ParseException e) {
throw new CustomException("Date format incorerect", e);
and I'm not sure how to write the test class for it.

This page should tell you everything you need to know. For the simplest case, which seems to be your case, just do this:
#Test(expected= CustomException.class)
public void myTest() {
MyObject obj = new MyObject();
obj.doSomethingThatMightThrowCustomException();
}

I hope this can help you.
public class YourTestClass
{
#Test
public void yourTestMethodName() throws CustomeException {
//your logic goes here.
if (condition) {
throw new CustomeException(<Message to display while throwing an error>);
}
}
}
Also you can try the following site http://junit.sourceforge.net/javadoc/org/junit/Test.html

Related

Exception Wrapping possible? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I have an Exception 'OrekitException' that I want to wrap into my own Exception class.
How can I go about this?
e.g. In one of my methods:
private void configureOrekit() throws OrekitException{
try {
method logic...
} catch (OrekitException oe) {
System.out.println(OrekitException oe);
log.error(oe.getMessage());
}
My own Exception class:
public class MyException extends Exception {
public MyException ( String message )
{
super( message );
}
}
How can I incorporate OrekitException in MyException so whenever it is thrown, it's out of the MyException class?
Provide a constructor that also accepts the exception to wrap :
public class MyException extends Exception {
public MyException (String message, OrekitException exception){
super(message, exception);
}
}
or to wrap any exception use a broader type for the parameter :
public MyException (String message, Exception exception){
super(message, exception);
}
You could use it as :
private void configureOrekit() throws MyException{
try {
method logic...
} catch (OrekitException oe) {
throw new MyException("message useful...", oe);
}
Note that System.out.println() is not a way to trace an exception and that logging an exception and then wrap it in another exception that you throw is not good as you could still log it at any layer, it would make things not clear at all to find some duplicate error logs in log files...
In a general way, either log or throw/propagate the exception : not both.
Exceptions allow you to specify a cause. You can take a cause in your constructor, and pass it to Exception's constructor:
public class MyException extends Exception {
public MyException (String message, Exception cause){
super(message, cause);
}
}
And your method can then throw MyException:
private void configureOrekit() throws MyException{
try {
method logic...
} catch (OrekitException oe) {
System.out.println(OrekitException oe);
log.error(oe.getMessage());
throw new MyException("", oe);
}
}
This allows the stack trace from your MyException objects to have caused by... show details/trace of the original OrekitException

How to test the code with rethrowing exceptions?

I have a piece of code in my android app that catches one exception and rethrows it as another, custom exception extended from RuntimeException. And it seems impossible to be tested.
Take a look at the following code:
try { ... } catch (MalformedURLException e) {
throw new CustomMalformedDataException(downloadUrlString, e);
}
When I try to test the exception case, I write:
#Test(expected = CustomMalformedDataException.class)
public void exceptionsTest() throws Exception {
<code triggering the exception>
}
But i get Test running failed: Instrumentation run failed due to 'java.net.MalformedURLException'
When I write:
#Test(expected = MalformedURLException.class)
public void exceptionsTest() throws Exception {
<code triggering the exception>
}
I get java.lang.Exception: Unexpected exception, expected<java.net.MalformedURLException> but was<CustomMalformedDataException>
So how should I test this case?
Code of exception class:
public class CustomMalformedDataException extends RuntimeException {
public CustomMalformedDataException(String message, Throwable cause) {
super(message, cause);
}
public CustomMalformedDataException(String url, MalformedURLException cause) {
super("The package has an invalid \"downloadUrl\": " + url, cause);
}
}
UPDATE: It seems that either way tests stop execution at the point where the initial exception is thrown, even though it is caught. But in case this exception is expected, the execution continues and throws another exception, which is already not expected.
So I tried out your code and got a different error so I can't give you an answer, but I've got a way of testing errors I prefer using JUnit that will get you the results you need
#Rule
public final ExpectedException exception = ExpectedException.none();
#Test
public void testExceptionOccurs() throws Exception {
exception.expect(CustomMalformedDataException.class);
//code that casues exception to happen
}
I've run this plenty of times and it works with no issues when I need to test that my exceptions are occuring. I hope this at least helps giving you a solution to writing exception tests.
If you really need to test RuntimeException then have your test throw RuntimeException instead of Exception

How can I set the message on an exception in Java?

I want to set a custom exception message. However, I'm unsure of how to do this. Will I need to create a custom exception class or is there an easier way of doing this?
Most standard exception classes provide a constructor that takes a mesage, for example:
public UnsupportedOperationException(String message) {
super(message);
}
The above class simply calls its parent's constructor, which calls its parent's constructor, and so on, ultimately culminating in:
public Throwable(String message) {
...
}
If you create your own exception class, I think it's a good idea to following this convention.
You can only set the message at the creation of the exception. Here is an example if you want to set it after the creation.
public class BusinessException extends RuntimeException{
private Collection<String> messages;
public BusinessException(String msg){
super(msg);
}
public BusinessException(String msg, Exception cause){
super(msg, cause);
}
public BusinessException(Collection<String> messages){
super();
this.messages= messages;
}
public BusinessException (Collection<String> messages, Exception cause){
super(cause);
this.messages= messages;
}
#Override
public String getMessage(){
String msg;
if(this.messages!=null && !this.messages.isEmpty()){
msg="[";
for(String message : this.messages){
msg+=message+",";
}
msg= StringUtils.removeEnd(msg, ",")+"]";
}else msg= super.getMessage();
return msg;
}
}
Well, if the API offers an exception that suits your needs (IllegalArgumentException for example), just use it and pass your message in the constructor.
The best approach is to wrap the exception.
try {
my code that throws E;
} catch (final E e) {
throw new MyE("my message", e);
}
The Exception class (its parent, actually - Throwable) takes a message as an argument in its constructor:
throw new Exception("message") or Exception("message", innerException);
The root Exception class accepts a String custom message, as do (as far as I can tell) all of derivative classes.
So: no, you don't need to create a custom class. One of the existing exceptions probably covers your case (read their descriptions to find out which). If none of those are really satisfactory, then you can create an extension of Exception (or RuntimeException, etc.) and maintain the custom message constructor.
Try this code:
try{
throw new Exception("Test String");
}
catch(Exception ex){
System.out.println(ex.getMessage());
}
Another variant
public class MyCustomExceptionWithoutMessageInConstructor extends IllegalArgumentException {
private static final String ERROR_MESSAGE = "terrible error";
public MyCustomExceptionWithoutMessageInConstructor() {
super(ERROR_MESSAGE);
}
}

JUnit test — analysing expected Exceptions [duplicate]

This question already has answers here:
In Java how can I validate a thrown exception with JUnit?
(10 answers)
Closed 7 years ago.
In JUnit, I'm currently using annotation to expect an exception in my tests.
Is there a way to analyse this exception? For example, I expect a CriticalServerException, but I also want to verify the content of the getMessage method.
If you have JUnit 4.7 or above try ExpectedException
There is an example in this question, which is copied below:
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testRodneCisloRok(){
exception.expect(IllegalArgumentException.class);
exception.expectMessage("error1");
new RodneCislo("891415",dopocitej("891415"));
}
I'm not sure if you should. Using a try-catch block to check the error message is so junit3ish. We have this cool feature now that you can write #Test(expected=CriticalServerException.class) and you want to go "back" and use try-catch again to fetch an exception you expect, just for checking the error message?
IMO you should stay for the #Test(expected=CriticalServerException.class) annotation and ignore the error message. Checking the error message, which can be changed a lot as it is a more "human readable" string and not a technical value, can also be tricky. You are forcing the exception to have a specific error message, but you might not know who generated the exception and what error message he chose.
In general you want to test if the method throws the exception or not, and not what the actual error message looks like. If the error message is really so important you should maybe consider using a subclass of the exception it throws and check it in #Test(expected=...).
try{
//your code expecting to throw an exception
fail("Failed to assert :No exception thrown");
} catch(CriticalServerException ex){
assertNotNull("Failed to assert", ex.getMessage())
assertEquals("Failed to assert", "Expected Message", ex.getMessage());
}
try
{
// your code
fail("Didn't throw expected exception");
}
catch(CriticalServerException e)
{
assertEquals("Expected message", e.getMessage());
}
try {
// test code invacation
fail("Exception not throw!!!");
} catch(CriticalServerException ex) {
assertTrue("Invalid exception data", ex.toString().contains("error text"));
}
Use MethodRule as a common solution, if you have many test cases to test
public class ExceptionRule implements MethodRule {
#Override
public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
try {
base.evaluate();
Assert.fail();
} catch (CriticalServerException e) {
//Analyze the exception here
}
}
};
}
}
Then use the Rule to your test class:
#Rule public ExceptionRule rule = new ExceptionRule();
I don't think there is a way of doing it using annotation. You may have to fall back to try-catch way where in the catch block you can verify the message
Use catch-exception:
catchException(obj).doSomethingCritical();
assertTrue(caughtException() instanceof CriticalServerException);
assertEquals("Expected Message", caughtException().getMessage());
Look at fluent-exception-rule, it "combines Junit ExpectedException rule and AssertJ's assertions convenience. "
import pl.wkr.fluentrule.api.FluentExpectedException;
...
#Rule
public FluentExpectedException thrown = FluentExpectedException.none();
#Test
public void testDoSomethingCritical() {
thrown.expect(CriticalServerException.class).hasMessage("Expected Message").hasNoCause();
obj.doSomethingCritical();
}
If you want to compare message along with exception type then you can try below code snippet.
#Rule
public ExpectedException expectedException = ExpectedException.none();
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Parameter is not valid"); //check string contains
expectedException.expectMessage(CoreMatchers.equalTo("Parameter is not valid")); //check string equals
Note: This will work for junit 4.9 onward.
Java 8 solution
Here is a utility function that I wrote:
public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
try
{
runnable.run();
}
catch( Throwable throwable )
{
if( throwable instanceof AssertionError && throwable.getCause() != null )
throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
#SuppressWarnings( "unchecked" )
T result = (T)throwable;
return result;
}
assert false; //expected exception was not thrown.
return null; //to keep the compiler happy.
}
(taken from my blog)
Use it as follows:
#Test
public void testThrows()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
throw new RuntimeException( "fail!" );
} );
assert e.getMessage().equals( "fail!" );
}
Also, if you would like to read some reasons why you should not want to check the message of your exception, see this: https://softwareengineering.stackexchange.com/a/278958/41811

Spring AOP AfterThrowing vs. Around Advice

when trying to implement an Aspect, that is responsible for catching and logging a certain type of error, I initially thought this would be possible using the AfterThrowing advice. However it seems that his advice doesn't catch the exception, but just provides an additional entry point to do something with the exception.
The only advice which would also catch the exception in question would then be an AroundAdvice - either that or I did something wrong.
Can anyone assert that indeed if I want to catch the exception I have to use an AroundAdvice? The configuration I used follows:
#Pointcut("execution(* test.simple.OtherService.print*(..))")
public void printOperation() {}
#AfterThrowing(pointcut="printOperation()", throwing="exception")
public void logException(Throwable exception) {
System.out.println(exception.getMessage());
}
#Around("printOperation()")
public void swallowException(ProceedingJoinPoint pjp) throws Throwable {
try {
pjp.proceed();
} catch (Throwable exception) {
System.out.println(exception.getMessage());
}
}
Note that in this example I caught all Exceptions, because it just is an example. I know its bad practice to just swallow all exceptions, but for my current use case I want one special type of exception to be just logged while avoiding duplicate logging logic.
The Spring reference doc says:
"After throwing advice runs when a
matched method execution exits by
throwing an exception"
By then it's too late to catch the exception as it has already been thrown and the method has exited. The approach you've taken with the #Around advice is the only way to actually catch the exception and deal with it before the method exits.
Actually, it is possible to catch exception within AfterThrowing advice as well.
I know it is a convoluted example, but it works.
#Aspect
#Component
class MyAspect {
#Autowired
public Worker worker;
#Pointcut(value = "execution(public * com.ex*..*.*(..))")
public void matchingAll(){}
#AfterThrowing(pointcut = "matchingAll()", throwing = "e")
public void myAdvice(RuntimeException e){
Thread.setDefaultUncaughtExceptionHandler((t, e1) ->
System.out.println("Caught " + e1.getMessage()));
System.out.println("Worker returned " + worker.print());
}
}
#Component
class Worker {
public static int value = 0;
public int print() {
if (value++ == 0) {
System.out.println("Throwing exception");
throw new RuntimeException("Hello world");
} else {
return value;
}
}
}
#SpringBootApplication
#EnableAspectJAutoProxy
public class AdvicesDemo {
public static void main(String[] args) {
final ConfigurableApplicationContext applicationContext = SpringApplication.run(AdvicesDemo.class);
final Worker worker = applicationContext.getBean(Worker.class);
System.out.println("Worker returned " + worker.print());
System.out.println("All done");
}
}
As you can see it is more about how to catch originally thrown exception and thus prevent its propagation back to the caller.
Working example on GitHub (check com.example.advices package)

Categories