I know there are a number of questions on this topic, but all of them seem to assume one of two things:
You just want to test if an exception was thrown and not caught,
You should test the function that is inside of the try block
directly
I'm not sure how I can apply those options to this case. I have a small try/catch block, like so:
try {
o.getDataContainer().build(...);
o2.setDataContainer(o.getDataContainer());
} catch (final Exception e) {
LOGGER.error("Data set failed", e);
}
As you can see, if o.getDataContainer() returns null, an exception would be triggered. However, that exception is then caught, and the test tool considers it a successful test. Is it possible to test that the exception occurred without changing the code?
I ask because our logging system triggers a trouble ticket if it picks up an exception that is caught and logged. Since it is common human error to forget to guard something like this, I would like to write UTs that can test if an exception was triggered and caught. I can't remove the whole-program protection provided by the catch block, but the error would also cause a degradation of the user experience, since the data isn't being passed along. (I work in a place where minutes of site downtime equal millions of dollars lost.)
In other words: The exception is an error, and we want to log it and investigate it, but in case this manages to trigger on prod, we don't want to risk the whole site going down.
Note: This try/catch sits inside a much larger function with many such try/catch blocks. One could easily argue bad overall design, but fixing it is not an option (without a huge amount of free dev time, at least).
Update: As the task at hand does not allow me to spend a great deal of time on this, I went with a very simple generic test that would fail if the guard and catch were both removed so that I could move on. But, I'm leaving the question unanswered for now in hopes of continuing conversation. I would love to be able to write a simple UT for each new feature that fails if any exceptions are triggered and caught.
Ignoring the issues with this code (Sometimes you've gotta put lipstick on a pig, I guess), this is how I might handle the situation.
I'd use Mockito and mock o2, then use an Answer to ensure the method is invoked.
A test might look like this:
#RunWith(MockitoJUnitRunner.class)
public class TestClass{
#Mock
O2 o2;
#Mock
O1 o1;
boolean exceptionThrown = false;
#Test
public void test(){
Mockito.doAnswer(new Answer<Void>(){
public Void answer(InvocationOnMock invocation) throws Throwable {
exceptionThrown = true;
throw new RuntimeException("some message");
}
}).when(o2).setDataContainer(DataContainer.class);
}
}
Essentially, you can Mock out o2 in your example, and force the exception.
If this doesn't quite do what you want, you may need to mock LOGGER and verify that it's invoked with LOGGER.error("some message");. Unfortunately, mocking statics is not at all elegant, but it can be done with PowerMock.
You could add a custom handler to LOGGER that just throws when an error is logged. For java.util.logging you could do something like:
LOGGER.addHandler(new Handler() {
public void publish(LogRecord record) {
if ("Data set failed".equals(record.getMessage())) {
throw new RuntimeException(record.getThrown());
}
}
public void flush() {}
public void close() throws SecurityException {}
});
I think log4j calls it "Appender," but the same principle should work. See How to create a own Appender in log4j? or How to Create a Custom Appender in log4j2?
Related
So I am working with AspectJ to refactor my program to remove all logging calls from the main classes. Instead, all logging calls will occur via aspects. So far, here's what I've done successfully:
Catching all exceptions. Since I already have my exception handling pretty unified to begin with (Exceptions propagate up call stack until they reach my controller, then get caught), this wasn't too difficult. Using handle(Exception) I've got every catch block tied to an aspect that will log the exception before the catch block executes.
Debug information logging. Basic things like entering a particular method, etc. Again, relatively simple using before() and, sometimes, args() or thisJoinPoint.getArgs() to capture parameters.
The final thing I need to do, though, is properly log successful completion of key methods. Here is a minor example, of a block of code as it currently exists in my program, so I can better explain my meaning here:
private static void loadDefaultProperties(){
defaultProperties = new Properties();
try {
defaultProperties.load(
Main.class.getClassLoader().getResourceAsStream(
"default.properties"));
if(defaultProperties.size() == 0){
throw new IOException();
}
//THE CURRENT LOGGING LINE THAT NEEDS TO BE MOVED TO AN ASPECT
LOGGER.logp(Level.INFO, Main.class.getName(),
"loadDefaultProperties()",
"Default Properties file loaded successfully");
}
catch (IOException ex){
//THIS EXCEPTION IS LOGGED USING HANDLE(EXCEPTION) IN AN ASPECT
displayExceptionDialog(ex);
}
}
So, this method loads the default properties from the classpath. If it fails, an IOException is thrown. However, if an exception is not thrown, and it performs its task successfully, I want to log that as well.
This particular example is a relatively minor item that wouldn't be a huge deal to miss, but this is the style currently used everywhere in the application.
How would I configure a pointcut/advice in AspectJ to only run after this method completes, and recognize that it does so successfully?
PS. I've considered propagating the exception further up the call stack. That would allow me to use a simple after() returning(Object o) advice to accomplish this. If an exception is thrown, this advice will not run because the method won't return properly.
The problem with that is there aren't many levels higher than this in the call stack. This particular method in my example is called directly by my main method immediately following the program's initialization. In my controller class, there's only one level higher in the call stack for all of my methods there as well.
I guess I could do this, but I want to see if there's another option first, rather than pool all of those exceptions together in one place.
You can certainly use a pointcut to wrap anything in the call stack, including main():
public aspect WrapMain
{
pointcut mainMethod() : execution(public static void main(String[]));
before() : mainMethod() {
System.out.println("Starting application...");
}
after() : mainMethod() {
System.out.println("Terminating application...");
}
}
If you are generating aspects using Java, you can use the #AfterReturning and #AfterThrowing annotations to manage successful or exceptional cases.
#Pointcut("execution(your-method-signature-here)
public void yourPointcut(){}
#AfterReturning(pointcut = "yourPointcut()", returning ="returnValue")
public void afterSuccessAdvice(JoinPoint jp, Object returnValue) {
// log here
}
#AfterThrowing(pointcut = "yourPointcut()", returning ="returnValue")
public void afterFailureAdvice(JoinPoint jp, Object returnValue) {
// log here
}
Here's a Javaworld article with examples that explains logging method entry and exit.
So I wrote the temporary method that looks like this:
public void tempMethod(String invalidCode) {
try {
long temp = Long.valueOf(invalidCode);
} catch (NumberFormatException ex) {
System.err.println("Wrong code format, code must contains numbers only. Your wrong code: " + invalidCode);
}
}
I want to write test for it with JUnit 4.10. The thing is solutions I found on web are not able to test it. I haven't really wrote any tests untill now so the question might be stupid.
Here is what I tried:
#Test(expected = NumberFormatException.class)
public void testEx() {
testInstance.tempMethod("asd");
}
And that says test failed, but exception message appears on output. I tried the test with use of
#Rule
public ExpectedException expectedEx = ExpectedException.none();
but this doesn't work for that case either.
Is there any option to check this method without changing tempMethod body?
Your method does not throw an exception, that's why the test fail.
You see, when an exception is thrown and caught inside the method, then you have in effect handled the exception: the programmer decided that this exception is not important and is just printing it, without throwing it further or stopping execution.
So the only way to test this is to check the standard error stream to see if the appropriate string was written to it. The exception is gone as soon as the catch block is closed.
as you pointed out yourself, the test fails because you are not throwing the exception, you caught it inside the method.
Anyway your method should either return something or have some side effect (quite probably a different one when it completes successfully and when it catches an exception), otherwise it isn't doing anything. That is what you should test.
Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions? Maybe compiler flags?
I know the reason why the catching is promoted, but want to do simple and straight tools that enforce their requirements. So if something can went wrong I don't like to catch up but exit the application, crashing with a meaningful exception. Usually this ends up like:
try {
connection.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
which introduces 4 lines of code mess, and introduces the wrapping RuntimeException mess on error output. Sometimes it even motivate people to wrap large try ... catch (Throwable ..) blocks around anything, which is the likely cause for our beloved 'Unknown error occured' alert boxes...
you can use throws keyword with method prototype to avoid try-catch block. which eventually throws the exception to JVM's Default Exception handler which halts the application if no catch block's are specified in your code to handle the exception raised.
Crashing the application at the first sight of an exception is very bad practice. Especially when some work is unsaved and the application is using some resources that needs to be freed and cleaned before the application terminates execution. Some very popular software used to do that... and instead of "fixing" the issue, they introduced a data recoverability features on application restart. However the trick, this is not good software engineering.
At the very least, your application should not crash on the first exception/error encountered, but recover with a meaningful message. It is being lazy to just wrap everything in a RuntimeException (or even Throwable) and, especially, not do anything with it.
Java does not support flags of any kind because there are 1) a workaround, and 2) better ways to handle this situation. For example :
1. Handle the exception in the calling method
You can add the throws keyword in your method declaration, up to your static public void main method, which, if not handling the exception, will eventually crash the application with a stacktrace.
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) throws Throwable {
new Foo().someMethod();
}
}
This method does not offer any means of recoverability and will probably make your user unhappy (with a big meaningless stachtrace if they ran the application from a console, or just nothing at all if they launched it from a shortcut or GUI). Also, if you have some acquired resources, you will not be able to clean them when an exception occurs. At the very least, your main should catch (Throwable e) and output something before throwing the exception above. Something like :
class Foo {
public void someMethod(....) throws IllegalArgumentException, IOException {
...
}
static public void main(String...args) {
try {
new Foo().someMethod();
} catch (...) {
// output or log exception here and, optionally, cleanup and exit
}
}
}
** EDIT **
Consider this scenario : a program is initializing some resource for processing some data, then some runtime exception (or error) occurs during processing, the application crash, but the resources are not released or freed. In Java, however, one could do this
public E doSomething() throws RuntimeException {
// declare a bunch of resources
try {
// process resources with unchecked exceptions
} finally {
// free resources
}
// return some result
}
and cleanly exit the method on error or on success, perhaps even logging the runtime error for "posterity".
2. Log the error and return some meaningful value
Logging is a very good practice. You can show your user some message telling them that the operation could not be executed without crashing the whole thing, and giving you some traces of what and where the user were doing. A simplistic logging system could be :
class Foo {
static private final Logger LOG = Logger.getLogger(Foo.class.getName());
public boolean doSomethingImpl(...) {
boolean result = true;
try {
...
} catch (SomeException e) {
LOG.log(Level.SEVERE, "meaningful message why method could not do something!", e);
result = false;
}
return result;
}
public void doSomething() {
if (!doSomethingImpl(...)) {
// handle failure here
}
}
}
By default, the Logger will output everything to the err output stream, but you can add your own handlers :
// loggers are singletons, so you can retrieve any logger at anytime from
// anywhere, as long as you know the logger's name
Logger logger = Logger.getLogger(Foo.class.getName());
logger.setUseParentHandlers(false); // disable output to err
logger.addHandler(new MyHandler()); // MyHandler extends java.util.logging.Handler
Java already ships with some default logging handlers, one of which writes to file.
etc.
Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions?
For a checked exception, you can chose between catching the exception and declaring it in the method header as thrown.
Maybe compiler flags?
No. There are no compiler flags to relax this. It is a fundamental part of the language design. Relaxing the checked exception rules via a compiler switch would cause serious library interoperability problems.
I don't think that there's any way around this for the JVM. Your best bet is to have your methods re-throw the exception, which gets rid of the "mess" in your code, and then have your main program throw Exception. This should propagate the error up to the top of your program.
Keep in mind, however, that the place where the exception actually happens is a much better place to let the user know what happened (i.e., exactly what it was doing when this particular IOException happened). You'll lose this resolution if all errors are simply propagated up to the top level.
You do have the ability to throw your exceptions up a level. Here's an example
public class Foo {
public Foo() {
super();
}
public void disconnect(connection) throws IOException {
connection.close();
}
}
Use "Throws" to avoid the error..but it will not be good programimg practice
As you know, exception is thrown at the condition of abnormal scenarios. So how to analog these exceptions? I feel it is challenge. For such code snippets:
public String getServerName() {
try {
InetAddress addr = InetAddress.getLocalHost();
String hostname = addr.getHostName();
return hostname;
}
catch (Exception e) {
e.printStackTrace();
return "";
}
}
Does anybody have good ideas?
You can tell junit that the correct behavior is to get an exception.
In JUnit 4, it goes something like:
#Test(expected = MyExceptionClass.class)
public void functionUnderTest() {
…
}
Other answers have addressed the general problem of how to write a unit test that checks that an exception is thrown. But I think your question is really asking about how to get the code to throw the exception in the first place.
Take your code as an example. It would be very hard to cause your getServerName() to internally throw an exception in the context of a simple unit test. The problem is that in order for the exception to happen, the code (typically) needs to be run on a machine whose networking is broken. Arranging for that to happen in a unit test is probably impossible ... you'd need to deliberately misconfigure the machine before running the test.
So what is the answer?
In some cases, the simple answer is just to take the pragmatic decision and not go for total test coverage. Your method is a good example. It should be clear from code inspection what the method actually does. Testing it is not going to prove anything (except see below **). All you are doing is improve your test counts and test coverage numbers, neither of which should be project goals.
In other cases, it may be sensible to separate out the low-level code where the exception is being generated and make it a separate class. Then, to test the higher level code's handling of the exception, you can replace the class with a mock class that will throw the desired exceptions.
Here is your example given this "treatment". (This is a bit contrived ... )
public interface ILocalDetails {
InetAddress getLocalHost() throws UnknownHostException;
...
}
public class LocalDetails implements ILocalDetails {
public InetAddress getLocalHost() throws UnknownHostException {
return InetAddress.getLocalHost();
}
}
public class SomeClass {
private ILocalDetails local = new LocalDetails(); // or something ...
...
public String getServerName() {
try {
InetAddress addr = local.getLocalHost();
return addr.getHostName();
}
catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
Now to unit test this, you create a "mock" implementation of the ILocalDetails interface whose getLocalHost() method throws the exception you want under the appropriate conditions. Then you create a unit text for SomeClass.getServerName(), arranging that the instance of SomeClass uses an instance of your "mock" class instead of the normal one. (The last bit could be done using a mocking framework, by exposing a setter for the local attribute or by using the reflection APIs.)
Obviously, you would need to modify your code to make it testable like this. And there are limits to what you can do ... for example, you now cannot create a unit test to make the real LocalDetails.getLocalHost() method to throw an exception. You need to make a case-by-case judgement as to whether it is worth the effort of doing this; i.e. does the benefit of the unit test outweigh the work (and extra code complexity) of making the class testable in this way. (The fact that there is a static method at the bottom of this is a large part of the problem.)
** There is a hypothetical point to this kind of testing. In your example, the fact that the original code catches an exception and returns an empty string could be a bug ... depending on how the method's API is specified ... and a hypothetical unit test would pick it up. However, in this case, the bug is so blatant that you would spot it while writing the unit test! And assuming that you fix bugs as you find them, the unit test becomes somewhat redundant. (You wouldn't expect someone to re-instate this particular bug ...)
Okay there are a few possible answers here.
Testing for an exception itself is easy
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
#Test
public void TestForException() {
try {
doSomething();
fail();
} catch (Exception e) {
assertThat(e.getMessage(), is("Something bad happened"));
}
}
Alternately, you can use the Exception Annotation to note that you expect an exception to come out.
Now, as to you specific example, Testing that something you are creating inside your method, either via new or statically as you did, when you have no way to interact with the object is tricky. You normally need to encapsulate that particular generator and then use some mocking to be able to override the behavior to generate the exception you expect.
Since this question is in community wiki I'll add a new one for completeness:
You can use ExpectedException in JUnit 4
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void TestForException(){
thrown.expect(SomeException.class);
DoSomething();
}
The ExpectedException makes the thrown exception available to all test methods.
Is is also possible to test for a specific error message:
thrown.expectMessage("Error string");
or use matchers
thrown.expectMessage(startsWith("Specific start"));
This is shorter and more convenient than
public void TestForException(){
try{
DoSomething();
Fail();
}catch(Exception e) {
Assert.That(e.msg, Is("Bad thing happened"))
}
}
because if you forget the fail, the test can result in a false negative.
Many unit testing frameworks allow your tests to expect exceptions as part of the test. JUnit, for example, allows for this.
#Test (expected=IndexOutOfBoundsException.class) public void elementAt() {
int[] intArray = new int[10];
int i = intArray[20]; // Should throw IndexOutOfBoundsException
}
How can I detect when an Exception has been thrown anywhere in my application?
I'm try to auto-magically send myself an email whenever an exception is thrown anywhere in my Java Desktop Application. I figure this way I can be more proactive.
I know I could just explicitly log and notify myself whenever an exception occurs, but I'd have to do it everywhere and I might(more likely will) miss a couple.
Any suggestions?
You probobly don't want to mail on any exception. There are lots of code in the JDK that actaully depend on exceptions to work normally. What I presume you are more inerested in are uncaught exceptions. If you are catching the exceptions you should handle notifications there.
In a desktop app there are two places to worry about this, in the event-dispatch-thread (EDT) and outside of the EDT. Globaly you can register a class implementing java.util.Thread.UncaughtExceptionHandler and register it via java.util.Thread.setDefaultUncaughtExceptionHandler. This will get called if an exception winds down to the bottom of the stack and the thread hasn't had a handler set on the current thread instance on the thread or the ThreadGroup.
The EDT has a different hook for handling exceptions. A system property 'sun.awt.exception.handler' needs to be registerd with the Fully Qualified Class Name of a class with a zero argument constructor. This class needs an instance method handle(Throwable) that does your work. The return type doesn't matter, and since a new instance is created every time, don't count on keeping state.
So if you don't care what thread the exception occurred in a sample may look like this:
class ExceptionHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
handle(e);
}
public void handle(Throwable throwable) {
try {
// insert your e-mail code here
} catch (Throwable t) {
// don't let the exception get thrown out, will cause infinite looping!
}
}
public static void registerExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
System.setProperty("sun.awt.exception.handler", ExceptionHandler.class.getName());
}
}
Add this class into some random package, and then call the registerExceptionHandler method and you should be ready to go.
The new debugging hooks in Java 1.5 let you do this. It enables e.g. "break on any exception" in debuggers.
Here's the specific Javadoc you need.
Check out Thread.UncaughtExceptionHandler. You can set it per thread or a default one for the entire VM.
This would at least help you catch the ones you miss.
If you're using a web framework such as Spring then you can delegate in your web.xml to a page and then use the controller to send the email. For example:
In web.xml:
<error-page>
<error-code>500</error-code>
<location>/error/500.htm</location>
</error-page>
Then define /error/500.htm as a controller. You can access the exception from the parameter javax.servlet.error.exception:
Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
If you're just running a regular Java program, then I would imagine you're stuck with public static void main(String[] args) { try { ... } catch (Exception e) {} }
If you are using java 1.3/1.4, Thread.UncaughtExceptionHandler is not available.
In this case you can use a solution based on AOP to trigger some code when an exception is thrown. Spring and/or aspectJ might be helpful.
In my current project I faced the similar requirement regarding the errors detection. For this purpose I have applied the following approach: I use log4j for logging across my app, and everywhere, where the exception is caught I do the standard thing: log.error("Error's description goes here", e);, where e is the Exception being thrown (see log4j documentation for details regarding the initialization of the "log").
In order to detect the error, I use my own Appender, which extends the log4j AppenderSkeleton class:
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent;
public class ErrorsDetectingAppender extends AppenderSkeleton {
private static boolean errorsOccured = false;
public static boolean errorsOccured() {
return errorsOccured;
}
public ErrorsDetectingAppender() {
super();
}
#Override
public void close() {
// TODO Auto-generated method stub
}
#Override
public boolean requiresLayout() {
return false;
}
#Override
protected void append(LoggingEvent event) {
if (event.getLevel().toString().toLowerCase().equals("error")) {
System.out.println("-----------------Errors detected");
this.errorsOccured = true;
}
}
}
The log4j configuration file has to just contain a definition of the new appender and its attachement to the selected logger (root in my case):
log4j.rootLogger = OTHER_APPENDERS, ED
log4j.appender.ED=com.your.package.ErrorsDetectingAppender
You can either call the errorsOccured() method of the ErrorsDetectingAppender at some significant point in your programs's execution flow or react immidiately by adding functionality to the if block in the append() method. This approach is consistent with the semantics: things that you consider errors and log them as such, are detected. If you will later consider selected errors not so important, you just change the logging level to log.warn() and report will not be sent.
In this case I think your best bet might be to write a custom classloader to handle all classloading in your application, and whenever an exception class is requested you return a class that wraps the requested exception class. This wrapper calls through to the wrapped exception but also logs the exception event.
I assume you don't mean any Exception but rather any uncaught Exception.
If this is the case this article on the Sun Website has some ideas. You need to wrap your top level method in a try-catch block and also do some extra work to handle other Threads.
Sending an email may not be possible if you are getting a runtime exception like OutOfMemoryError or StackOverflow. Most likely you will have to spawn another process and catch any exceptions thrown by it (with the various techniques mentioned above).
There is simply no good reason to be informed of every thrown exception. I guess you are assuming that a thrown exception indicates a "problem" that your "need" to know about. But this is wrong. If an exception is thrown, caught and handled, all is well. The only thing you need to be worried about is an exception that is thrown but not handled (not caught). But you can do that in a try...catch clause yourself.