I am writing test using EasyMock and there is a piece of source code like this:
public void doSomething(){
try
{
// Do something
}
catch (RejectedExecutionException ex)
{
// just add some metrics here, no big action
}
}
i am writing test for the case throwing RejectedExecutionException, but exception is not thrown finally, which means i can't use ExpectedException. So how should i test this exception is thrown once with EasyMock?
I do not think that you have a clean way to do this with any mockup framework. I however can suggest you the following solutions.
Solution 1
Modify you code of doSomething() as following:
public void doSomething(){
try
{
doSomethingImpl(); // throws RejectedExecutionException
}
catch (RejectedExecutionException ex)
{
// just add some metrics here, no big action
}
}.
Now implement test for both doSomethingImpl() that should throw exception and doSomething() that should not with the same input data and state.
Solution 2
You catch code does something, doesn't it? For example calls log.error(). You can verify that specific call indeed happened and happened only once. I do not remember the specific syntax to do this with EasyMock, but with Mockito it is very simple: use Mockito.verify().
Solution 3
You can use PowerMock to check that constructor of you exception was called. It is not very clean because theoretically you can create instance of exception but do not throw it, but it is better than nothing.
Probably you can even combine these solutions. However I believe that the first is the best one.
The Do something part calls a mock throwing the exception?
If yes, just do expect(mock.methodCalled()).andThrow(new RejectedExecutionException());
And then EasyMock.verify(mock) at the end of your test. This will make sure methodCalled was called once and only once.
Related
Is it possible to #Test if an appropriate exception was thrown in the main code function eaven if it was catch in a try / catch block?
ex:
public int maxSum(int a, int b) {
try {
if (a + b > 100)
throw new TooMuchException("Too much! Sum reduced to 50");
} catch (TooMuchException e) {
System.out.println(e);
return 50;
}
return a + b;
}
To be tested by somethink like this
#Test
void maxSum_TooMuchExceptionThrowedAndCatchedWhenSumOfNumbersIsOver100() {
Service service = new Service();
assertThatThrownBy(() -> {
service.maxSum(55, 66);
}).isInstanceOf(TooMuchException.class)
.hasMessageContaining("Too much! Sum reduced to 50");
}
.
public class TooMuchException extends Throwable {
public TooMuchException(String message) {
super(message);
}
}
Test Exception not the message.
I care about this because I want to be able to catch exceptions in function without crashing the program.
The test's job is to confirm that the code's behavior is as expected, which means: the code does what it needs to do. Tests should not verify implementation details.
Your exception being thrown and caught is an implementation detail because the outside program doesn't know or care about it. In this case it would be very reasonable to look at this code and conclude that throwing an exception here is useless (or badly performing, because creating a stack trace has a cost) and it should be removed. Yet if you add code in the test to check for the exception somehow, say by reading the stack trace written to stdout (very do-able if you know the io classes, just fiddly and brittle), then you will have wasted your time implementing that check and you will also make extra work for the task of changing the implementation. Somebody has to look at it, understand it, and check that it's safe to remove it.
That is why we try to avoid testing implementation details, there is always the chance we will have a defect or performance issue or design change that requires modifying our implementation. We can't always avoid rewriting the test, sometimes part of the problem is that the contract was not defined right or circumstances' changing have made it irrelevant. But if we can have the test check behavior only, then we have a better chance of bring able to write a new implementation and run it against the old test, verifying that the new version does what the old one did. Updating tests is work and we want to minimize our workload when maintaining tests.
I'm writing unit tests for an application that already exists for a long time. Some of the methods I need to test are build like this:
public void someMethod() throws Exception {
//do something
}
If I want to test these methods I have to write something like this in my unit test:
#Test
public void someTest() {
try {
someMethod();
}
catch (Exception e) {
e.printStackTrace();
}
}
Is it a good practice to do this? Or is there an other way to test these methods?
I did some research on the internet and I found a few solutions with the #Rule annotation and #Test(expected=Exception.class), but that's not working (Eclipse keeps showing the someMethod() line in the test as wrong).
I don't know if these are good solutions, because I'm pretty new to the whole unit testing story.
If someone who knows a lot about this could help me out, I would be really thankful.
Since Exception is a checked exception, you either:
Have to catch the exception in a try...catch statement, or
Declare the exception to be thrown in the method itself.
What you have up there works fine, but my personal preference is to declare the exception to be thrown. This way, if an exception I'm not expecting is thrown during the run of the test, the test will fail.
#Test
public void someTest() throws Exception {
// dodgy code here
}
If we need to see if a specific exception is thrown, then you have the option of using #Rule or adding the value to the #Test annotation directly.
#Test(expected = FileNotFoundException.class)
public void someTest() throws Exception {
// dodgy code here
}
In JUnit 5, you can leverage Assertions.assertThrows to accomplish the same thing. I'm less familiar with this overall since it's not yet GA at the time of editing, but it appears to accept an Executable coming from JUnit 5.
#Test
public void someTest() {
assertThrows(FileNotFoundException.class, () ->
{ dodgyService.breakableMethod() };
}
#Test
public void someTest() {
try {
someMethod();
}
catch (Exception e) {
Assert.fail("Exception " + e);
}
}
Is what you can do, if the exception should not occur. An alternative would be to throw the exception in the signature like this:
#Test
public void someTest() throws Exception {
someMethod();
}
The difference is, that in one case the test will fail with an assertion exception and in the other case it will fail because the test crashed. (like somewhere in your code you get a NPE and the test will because of that)
The reason you have to do this, is because Exception is a checked exception. See Checked versus unchecked exception
The #Test(expected=Exception.class) is for tests, that want to test that the exception will be thrown.
#Test(expected=ArrayIndexOutOfBounds.class)
public void testIndex() {
int[] array = new int[0];
int var = array[0]; //exception will be thrown here, but test will be green, because we expect this exception
}
Do not catch your application's exception in your test code. Instead, declare it to be thrown upwards.
Because, when JUnit's TestRunner finds an exception thrown, it will automatically log it as an error for the testcase.
Only if you testcase expects that the method should thrown an Exception you should use #Test(expected=Exception.class) or catch the exception.
In other cases, just throw it upwards with,
public void someTest() throws Exception {
You can add exception in test method signature. Then, if you are testing whether exception is thrown, you have to use #Test(expected=Exception.class). In the test cases where exception has not to be thrown, test will pass successfully.
#Test
public void testCaseWhereExceptionWontBeThrown() throws Exception {
someMethod(); //Test pass
}
#Test(expected = Exception.class)
public void testCaseWhereExceptionWillBeThrown() throws Exception {
someMethod(); //Test pass
}
There are two main rules on how to process exceptions at Junit testers:
If the exception was originated into the tested code:
If it was expected, declare it in the expected attribute of the Test annotation. Or, if further checks should be done on the exception object itself, catch it and ignore it. (In this case, there must be also a call to Assert.fail at the end of the try block, to indicate that the expected exception was not produced).
If it was not expected, catch it and execute Assert.fail. (A previous call to Exception.printStackTrace is also useful).
If the exception was not originated into the tested code or it is not interesting to the test (for example, most of the IOExceptions are produced at network level, before the test could even be completed), rethrow it at the throws clause.
Why you should expect an exception in the tester? Remind: You should code one test method for every possible result on the tested code (in order to achieve a high code coverage): In your case, one method that must return successfully, and at least another one that must produce an Exception.
Three points about JUnit:
Tests should be precise, they should pass or fail unambiguously based solely on how the test inputs are set up.
Tests should have failures reported back into the framework.
Tests should not rely on having their output read.
Your example fails on all three counts. If an exception gets thrown or not, the test still passes. If an exception is thrown JUnit never finds out about it and can't include it in the test results. The only way to know something went wrong is to read what the test writes to stdout, which makes errors too easy to ignore. This is not a useful way to write tests.
JUnit was designed to make doing the right thing easy and to give developers useful feedback. If an exception gets thrown from a test method, it gets caught by the framework. If the test was annotated with an exception indicating that exception is expected, then the framework marks the test as passing. Otherwise the framework fails the test and records the stacktrace for reporting. The framework reports what assertions fail and what unexpected exceptions occurred so that everybody knows if the tests worked or not.
If you expect a test to succeed without throwing an exception, then if anything in the test can throw a checked exception, add throws Exception to the test method signature. Adding the throws to the signature doesn't say the method has to throw anything, it just lets any exceptions that happen to occur get thrown so that the test framework can catch them.
The only instance where you would actually catch the exception in the test is where you want to test assertions about the exception; for instance, you could test that the message on the exception is what you expect, or if the exception has a cause set on it. In that case you would add Assert.fail() at the end of the try-block so that not having an exception thrown will cause the test to fail.
It isn’t having a try-catch block that is so bad, it’s the absence of anything that will cause the test to fail that is bad.
When you write a test at first, make it fail. That way you prove to yourself that you know what the test is doing, and you confirm that, when there is a failure, you will be made aware of it.
What kind of exception is it? Is it
an exception from doing something like using streams that won't happen in your unit test or
an exception that can happen because of some kind of bad input?
If it's 1. I would just put it at the method signature level because a try-catch is serving no real purpose other than ceremony.
#Test
public void testFoo() throws Exception {
// ...
}
If it's 2. it becomes a little more complicated. You need to ask yourself what should be happening if the Exception is thrown. Should the test fail? Is it expected? Is it irrelevant? Examples below of how to handle all of these. BEWARE: I only used Exception because you did. I hope it really isn't though because if it's possible for some other exception to be thrown other than the expected then these will be very wonky. If possible don't use Exception, use something more specific (in the junit and code).
// The below code assumes you've imported the org.junit.Assert class.
#Test
public void thisShouldFailIfExceptionCaught() {
//Given...
try {
// When...
} catch (Exception e) {
Assert.fail();
}
// Then...
}
#Test
public void thisShouldPassOnlyIfTheExceptionIsCaught() {
//Given...
try {
// When...
Assert.fail();
} catch (Exception expected) {}
// No "then" needed, the fact that it didn't fail is enough.
}
#Test
public void irrelevantExceptionThatCouldBeThrown() {
//Given...
try {
// When...
} catch (Exception e) {}
// Then...
}
I've just started my very first toy-project in java and faced with misunderstanding of how it should be done. I'm using java.util.logging and JUnit4 library.
For example we have something like this:
public class SomeClass {
private static Logger log = Logger.getLogger(SomeClass.class.getName());
public static void SomeMethod() {
try{
...some code...
} catch(Exception e){
log.warning("Something bad happened");
}
}
And the unit-test will be:
#Test
public void SomeClassTest(){
SomeClass.SomeMethod();
}
But there will never be an exception, cause I've already handled it in method.
Should I generate new exception in catch-block? Or may be using junit combined with logging is not a good idea?
A method that does not throw an exception (and returns the expected value if any) is meant to work correctly from the perspective of a user.
So you should use try - catch and logging inside a method, when you can catch an exception and the method will still work correctly (do something else when this error happens for example but still return the expected result or perform the supposed operation).
In this case the unit test should check if the operation was performed correctly (if the object is in the expected state and the result value (in your case void) is correct
You should rethrow the exception (and usually not log it, but that depends) if the method cannot do what it is supposed to do when the exception occurs.
In this case the unit test should check if the operation was performed correctly (if the object is in the expected state and the result value (in your case void) is correct if there is no exception, and if there is an exception it should check if this exception was expected
If you want to test that the exception is thrown then you would have to re-throw, or not catch, the Exception.
Otherwise you can unit test that the class is in the correct state after the exception, i.e. that the exception was correctly handled.
I would say one other thing. Don't catch(Exception e), catch the specific exception you are expecting. Otherwise you will handle other, unexpected, exceptions in the same way and that is really quite dangerous.
You can simply rethrow the caught exception:
public class SomeClass {
private static Logger log = Logger.getLogger(SomeClass.class.getName());
public static void SomeMethod() {
try {
// your stuff
} catch (Exception e) {
log.warning("Something happened");
throw e;
}
}
}
Should I generate new exception in catch-block?
No. don't do that! you can test your existing code! when you only want to log the message but you don't want to handle it in the method that call someMethod() don't throw it!
using junit combined with logging is not a good idea?
both are good ideas and can be used together without problems.
Think about how you can test your method. i would not modify the code just that you can easily test it. because you WANTED to catch the exception and log for a reason.
try verifing what variables or objects are modified in your test-method
I have a fairly standard creational pattern whereby a class exposes a static method for returning instances of itself, like so:
public class MyClass {
private MyClass(/*parameter list*/) {
// internal construction
}
public static MyClass GetMyClass(/*parameter list*/) {
return new MyClass(/*parameter list*/);
}
}
...
//this line wont break in the debugger and seemingly never gets called - why?
MyClass inst = MyClass.GetMyClass(/*parameter list*/);
However, inst is always null. I can't break on the line that calls the static method, the debugger just ignores it - what's going on?
Edit: Thanks for the suggestions.
All projects have been cleaned and rebuilt (manully in NetBeans)
I have added a break in the static method and no it isn't hit.
Yes, the code above is being called (ultimately) in a constructor for a Swing 'FrameView' though it surely shouldn't matter where I am calling this from, should it?
There is no exception swallowing anywhere
Side note, other than the missing class declaration (which was a typo) why is this not valid Java? Why is this obviously C# code? Explanations would be more helpful than downvotes :)
Edit II: The Params is just supposed to indicate a whole load of parameters - sorry if this confused anyone, I obviously know parameters have type declarations and so on, the code above was intended as a quick shorthand version rather than a full and (complicated) real sample...
A couple of options:
An exception is being thrown which you're somehow missing
You're not debugging the code that you think you are (i.e. your built code is out of date with your source code)
The latter is the most likely one, IMO.
Apparently you're swallowing an exception inside the constructor something like:
try {
// Something.
} catch (Exception e) {
}
You should never do that. It makes debugging and nailing down the root cause much harder. Rather throw it or at least do a e.printStackTrace(). If throwing and you don't want to use the throws clause for some reasons, consider using a RuntimeException (or one of its subclasses). E.g.
try {
// Something.
} catch (Exception e) {
throw new RuntimeException("Construction failed.", e); // Try to be more specific, e.g. IllegalArgumentException or so. Or just write robust code, i.e. nullchecks and so on.
}
or (but in my opinion not very applicable in your case):
try {
// Something.
} catch (Exception e) {
e.printStackTrace();
}
I understand that you are trying to make a simple example to show your problem, however if you add the appropriate type statements into your sample code, then it both compiles and does what you expect.
However, in your original codebase you could simply place the breakpoint in the static method to see whether or not it is called.
Maybe a simple question, but you never know… are you sure that you are running the code that you think you are running? That is, is everything recompiled and built from the latest sources?
There is nothing wrong with :
MyClass inst = MyClass.GetMyClass(Params);
It depends what is before or after that line of code.
Start by doing this:
public class MyClass
{
private MyClass(/*parameter list*/)
{
System.out.println("entering MyClass(...)");
// internal construction
System.out.println("leaving MyClass(...)");
}
// Java uses lower case for method names - so get not Get
public static MyClass getMyClass(/*parameter list*/)
{
final MyClass foo;
System.out.println("entering getMyClass(...)");
foo = new MyClass(...);
System.out.println("leaving getMyClass(...)");
return (foo);
}
}
...
MyClass inst = MyClass.getMyClass(/*parameter list*/);
See if outside the debugger the code gets called.
If you are catching any exceptions, at the very least do:
catch(final WhateverException ex)
{
// at the very least do this so you can see that the exception happens
ex.printStackTrace();
}
Avoid catching Throwable, Error, Exception, and RuntimeException. Infact the best way do do it is get rid of all the catch statements and then only add catches for what the compiler tells you that you have to have.
The other thing is you do not say where MyClass inst = MyClass.getMyClass(/parameter list/); is called from. It is entirely possible that that line never gets hit.
You mention that you're calling this from the constructor of a FrameView, but I assume you're talking about an implementation or extension of that interface/object. My reasoning was to make sure you wern't recursively invoking the constructor.
I think the reason why catching java.lang.Exception isn't catching the problem is because it is likely too specific in this case. Try catching java.lang.Throwable which will catch errors like java.lang.NoClassDefFoundError - that frequently crops up when you have a jar missing somewhere.
I want to implement exception checking (like in JUnit 4) using JUnit 3. For example, I would like to be able to write tests like this:
public void testMyExceptionThrown() throws Exception {
shouldThrow(MyException.class);
doSomethingThatMightThrowMyException();
}
This should succeed if and only if a MyException is thrown.
There is the ExceptionTestCase class in JUnit, but but I want something that each test* method can decide to use or not use. What is the best way to achieve this?
Would the solution:
public void testMyExceptionThrown() throws Exception {
try {
doSomethingThatMightThrowMyException();
fail("Expected Exception MyException");
} catch(MyException e) {
// do nothing, it's OK
}
}
be suitable for what you're thinking of?
Also have a look at this thread, where someone created a Proxy-solution for JUnit3 which seems to be another possibility to solve your problem.
There is no need to implement your own solution because there is already one that can be used with JUnit3 (and any other testing framework): catch-exception.
The simplest approach is to use the Execute Around idiom to abstract away the try-catch that you would usually write.
More sophisticated is to note that TestCase is just a Test. I forget the details, but we can override the execution of the test (which the framework initially calls through run(TestResult) specified in Test). In that override we can place the try-catch, as per Execute Around. The testXxx method should call a set method to install the expected exception type.