A test should fail on throwing exception - java

#Test
public void testA() throws Exception {
}
Is above a good style to code ? Because the test is allowed to throw exceptions and if the code throws exception, then Netbeans consider that as a successful test case.
If yes, then I want to make the test fail if it throws any exception, how can I do that ?

Your code is perfectly valid if you want the test to fail if any exception occurs. Imho this is good style if a checked exception may be thrown in the test code, but should not occur.
If you wish to test exception generation on a specific line or wish to verify something on the exception itself, this pattern is usually more helpful:
#Test
public void testA() {
// Initialize
try {
// Except Exception here
Assert.fail("Exception not thrown");
} catch (IWantToCatchException ex) {
// Assert exception is correct
}
// other code
}

To pass a test when an exception is thrown you need to set the expected element of the Test annotation.
#Test(expected=Exception.class)
Otherwise jUnit will fail the test if an exception is thrown, which may be appropriate in your case.

Since JUnit 4.7 there is the expected part in the annotation of tests:
#Test(expected=YourException.class)
With this the test succeeds only if the exception is thrown.
Therefore, if you leave expected out, the test fails whenever an exception is thrown.

Exceptions are the rare cases which you don't know will happen or not, but you take precautions. But in case of unit testing if you are assured of that it will throw certain exception then test it that way like :
#Test(expected = ArithmeticException.class)
public void testA() {
int i = 1/0;
}

Related

test exception is not thrown

I'm creating an integration test:
#RunWith(CdiRunner.class)
#AdditionalClasses({FollowUpActivityRepository.class, SettingsPropertiesProducer.class})
public class FollowUpActivityFeaturesTest {
#Inject protected FollowUpActivityService fuaService;
#Test
public void DigitalInputTOFollowUpActivityFIELDS()
{
FollowUpActivityDTO dto = new FollowUpActivityDTO();
dto.setId("id");
dto.setTimestamp(Date.from(Instant.now()));
dto.setDueTimestamp(Date.from(Instant.now()));
dto.setClosingTimestamp(Date.from(Instant.now()));
dto.setMatter("matter");
dto.setComment("comment");
this.fuaService.createOrUpdate(dto);
}
}
createOrUpdate is like:
public void createOrUpdate(FollowUpActivityDTO dto) throws RepositorySystemException
So, I need to check this exception is NOT thrown.
I'd like to do it elegantly.
Actually, I'm using junit 4.12 and hamcrest 2.0.0.0.
Any ideas?
Example
In .NET, I'm using NSubstitute in order to get that:
this.apiClient.Invoking(c => c.GrantAuthorization()).ShouldNotThrow();
Edit after you reversed the meaning of the question:
If you want your test to fail if an Exception is thrown, you have nothing more to do than just declare an Exception in the throws part of the test method signature (this is not mandatory if the Exception thrown is some kind of RuntimeException, but yours obviously isn't):
public void DigitalInputTOFollowUpActivityFIELDS() throws Exception
No need to specify any kind of Exception. Anyway, any jUnit test will fail as soon as an unhandled Exception is thrown (which is the behavior you're expecting).
From this blog:
Test methods that declare that they throw one particular type of
exception are brittle because they must be changed whenever the method
under test changes.
Old answer:
Just write your test annotation like this:
#Test(expected=RepositorySystemException.class)
This way, the test method will succeed as soon as this exception is thrown.
See javadoc.
Edit after your comment:
To validate the test against any Exception, just:
#Test(expected=Exception.class)
But as B. Dalton suggested, that seems kind of dangerous, as this test would then pass on any Exception, no matter if it's the one you're expecting or any other.
For the sake of completeness, you can also do something like this (based on this answer):
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void DigitalInputTOFollowUpActivityFIELDS()
{
FollowUpActivityDTO dto = new FollowUpActivityDTO();
dto.setId("id");
dto.setTimestamp(Date.from(Instant.now()));
dto.setDueTimestamp(Date.from(Instant.now()));
dto.setClosingTimestamp(Date.from(Instant.now()));
dto.setMatter("matter");
dto.setComment("comment");
thrown.expect(Exception.class);
thrown.expectMessage("something you can check"); // if needed
this.fuaService.createOrUpdate(dto);
}
This way, createOrUpdate will still be able to validate the test by throwing any kind of Exception, but at least the rest of the method won't.
See javadoc for ExpectedException.
Or, of course, the good old solution:
try {
this.fuaService.createOrUpdate(dto);
fail("this should throw an exception");
} catch (RepositorySystemException e){
// pass
} catch (Exception e){
// pass
}
This is less elegant, but allows you to tweak the exception handling as you need.

How should a unit test deal with expected and unexpected exceptions?

Should it pass the test when the expected exception takes place?
Should it fail the test when an unexpected exception arises?
Is it redundant to handle the exception since it'll fail the test and therefore act as a test?
Test Expected Exceptions
You have to add the expected attribute with the expected exception, so the test will pass if the specified exception is thrown. Otherwise, it will fail.
For example:
#Test(expected=NullPointerException.class)
public void cannotConvertNulls() {
service.convert(null);
}
or...
#Test(expected = ArithmeticException.class)
public void divisionWithException() {
int i = 1/0;
}
Documentation says:
The Test annotation supports two optional parameters. The first,
expected, declares that a test method should throw an exception. If it
doesn't throw an exception or if it throws a different exception than
the one declared, the test fails.
Test Timemouts
Just to let you know, you can also test timeouts.
The second optional parameter, timeout, causes a test to fail if it
takes longer than a specified amount of clock time (measured in
milliseconds). The following test fails:
#Test(timeout=100)
public void infinity() {
while(true);
}
Hope to help
For expected exceptions there are really nice ways to do this with JUnit:
#Test(expected=NullPointerException.class)
public void testNullPointerExceptionIsThrown() {
ArrayList emptyList;
emptyList.size(); //or add, remove etc.
}
The above test in JUnit would pass because it was declared with the #Test annotation that the test method should expect that a null pointer exception is thrown.
If the test is to expect a particular exception will arise with certain data, then yes, it should pass if that particular exception is thrown.
If the test is to expect a particular exception will arise with certain data, or there is no expectation of an exception, then yes, it should fail if any exception outside of expected is thrown.
Do not handle the thrown exceptions yourself unless you have to (and if you have to, that's a test smell - revisit why you're handling exceptions). The best way to indicate to JUnit that you expect an exception is to use the expected field on the #Test annotation.
For example, let's say you were testing a Roman numeral converter, and said that anything not in the normal Roman numerals was an illegal argument (namely, P).
#Test(expected = IllegalArgumentException.class)
public void method_takesIllegalArgument_throwsIllegalArgumentException() {
convertRomanNumeralToNumber("PXL");
}
Exceptions are part of your API, and sometimes explicitly so. As such, you should document the exceptions that your code may throw, and write tests to ensure that they are upheld.
#Test(expected = ThisException.class) is an excellent place to start, if you have JUnit4 and are writing a method that will throw new ThisException(...). Note the value here of picking the most appropriate exception: If you get lazy and use expected = Exception.class, your code would accept it if you change to throw new ThatException(...) instead. Your non-exception code should pass if and only if no exceptions are thrown (which JUnit will enforce for you), and your tests should carefully specify exactly which exception to expect so they can fail if and only if that specific exception is thrown.
As dhiller noted in the comments, the ExpectedException rule is also a very good choice for JUnit4, and allows further inspection of the thrown exception:
#Rule ExpectedException expectedException = ExpectedException.none();
#Test public void yourTest() {
// This is for demonstration. Don't actually verify the exact exception message
// unless you want to have to update your test if the text ever changes.
expectedException.expectMessage("Error 743: Toilet paper missing.");
systemUnderTest.doStuff();
}
But if you really want to check state after catching an exception, the best way to go is JUnit3-style:
#Test public void yourTest() {
try {
systemUnderTest.doStuff();
fail("ThisException expected.");
} catch (ThisException expected) {
assertEquals(743, expected.getErrorNumber());
}
// In both #Test(expected=...) and ExpectedException code, the
// exception-throwing line will be the last executed line, because Java will
// still traverse the call stack until it reaches a try block--which will be
// inside the JUnit framework in those cases. The only way to prevent this
// behavior is to use your own try block.
// This is especially useful to test the state of the system after the
// exception is caught.
assertFalse(systemUnderTest.hasToiletPaper());
}
Another library that claims to help here is catch-exception; however, as of May 2014, the project appears to be in maintenance mode (obsoleted by Java 8), and much like Mockito catch-exception can only manipulate non-final methods.

JUnit Testing Exceptions [duplicate]

This question already has answers here:
How do you assert that a certain exception is thrown in JUnit tests?
(35 answers)
Closed 8 years ago.
I'm really new to java.
I'm running some JUnit tests on a constructor. The constructor is such that if it is given a null or an empty string for one of its parameters, it's supposed to throw an exception.
When I test this constructor in JUnit with a null or an empty string parameter, I get a red bar, even though I'm almost 100% sure that the constructor method does indeed throw an exception when such parameters are passed in to it.
Shouldn't there be a green bar in JUnit if the method throws an exception the way it is supposed to? Or is it that when you are supposed to get a red bar when the exception throwing works the way it is supposed to?
#Test(expected = Exception.class)
Tells Junit that exception is the expected result so test will be passed (marked as green) when exception is thrown.
For
#Test
Junit will consider test as failed if exception is thrown, provided it's an unchecked exception. If the exception is checked it won't compile and you will need to use other methods.
This link might help.
are you sure you told it to expect the exception?
for newer junit (>= 4.7), you can use something like (from here)
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testRodneCisloRok(){
exception.expect(IllegalArgumentException.class);
exception.expectMessage("error1");
new RodneCislo("891415",dopocitej("891415"));
}
and for older junit, this:
#Test(expected = ArithmeticException.class)
public void divisionWithException() {
int i = 1/0;
}
If your constructor is similar to this one:
public Example(String example) {
if (example == null) {
throw new NullPointerException();
}
//do fun things with valid example here
}
Then, when you run this JUnit test you will get a green bar:
#Test(expected = NullPointerException.class)
public void constructorShouldThrowNullPointerException() {
Example example = new Example(null);
}
An adventage of use ExpectedException Rule (version 4.7) is that you can test exception message and not only the expected exception.
And using Matchers, you can test the part of message you are interested:
exception.expectMessage(containsString("income: -1000.0"));
Though #Test(expected = MyException.class) and the ExpectedException rule are very good choices, there are some instances where the JUnit3-style exception catching is still the best way to go:
#Test public void yourTest() {
try {
systemUnderTest.doStuff();
fail("MyException expected.");
} catch (MyException expected) {
// Though the ExpectedException rule lets you write matchers about
// exceptions, it is sometimes useful to inspect the object directly.
assertEquals(1301, expected.getMyErrorCode());
}
// In both #Test(expected=...) and ExpectedException code, the
// exception-throwing line will be the last executed line, because Java will
// still traverse the call stack until it reaches a try block--which will be
// inside the JUnit framework in those cases. The only way to prevent this
// behavior is to use your own try block.
// This is especially useful to test the state of the system after the
// exception is caught.
assertTrue(systemUnderTest.isInErrorState());
}
Another library that claims to help here is catch-exception; however, as of May 2014, the project appears to be in maintenance mode (obsoleted by Java 8), and much like Mockito catch-exception can only manipulate non-final methods.

Stubbing a checked exception: how to handle the exception

I am using Junit 4 and Mockito and I want to stub a method call so that it throws an exception:
doThrow(MyException.class).when(myObject).foo();
The problem is, MyException is a checked exception, so the call to foo() in this statement causes the compiler to complain that I must either handle the exception or add a throws clause to my method.
So I am wondering what the right way to handle this situation is? My thoughts so far have been:
I am using it wrong and there is a better way to do it.
I just add throws MyException to the test method
I extract the call out to another method that just swallows the exception
e.g.
private void givenFooThrowsAnException(MyObject myObject) {
try {
doThrow(MyException.class).when(myObject).foo();
} catch (MyException e) {
// Required to stub a checked exception
}
}
While the stubbing forces you to handle the checked exception, it will actually never throw that exception. The most elegant approach is to declare the test method to throw that exception.
There is only one caveat with that approach. If your test actually verifies that the checked exception is thrown by declaring it in the #Test annotation.
#Test(expected=MyException.class)
public void test...() throws MyException {
//...
}
In that case if your stubbing gets messed up and does throw the checked exception, it may yield a passing test that probably should have failed.
Alternatively you could simply use unchecked exceptions.

Why does CodePro junit test methods throw Exception (in Eclipse)?

Eclipse's CodePro generates JUnit tests, however, all test methods that it generates throw Exception even if it is impossible for a checked exception to be thrown. Is this a limitation of CodePro, or a good JUnit practice I haven't seen before?
For example:
#Test
public void testCategory_1()
throws Exception {
String categoryName = "";
Category result = new Category(categoryName);
// add additional test code here
assertNotNull(result);
assertEquals(null, result.getCategoryName());
}
Where new Category(String) and result.getCategoryName() don't throw any checked exceptions.
In the case above, you can remove the throws Exception with no problems. However, in the case where you do have an checked Exception, the code becomes much simpler to manage if you just add the throws Exception. Look at the alternative:
#Test public static void testIt() {
try {
foobar(); // throws an IOException
} catch (Exception e) {
fail("caught an exception " + e.getMessage());
}
}
as opposed to:
#Test public static void testIt() throws IOException {
foobar();
}
JUnit handles Exceptions exactly the same as assertion failures (which is actually implemented as an AssertionError), so if there is an unexpected exception in your code it will result in a failed test, which is probably what you want. And your test is much clearer
If you have an expected exception, then you can either specify it as expectedException in the #Test annotation or using a TestRule ExpectedException.
I use this a lot when I have checked exceptions in my code. It's a lot easier to add throws Exception to your test method rather than a list of all of the checked Exceptions. You do fall foul of some checkstyle rules though :-)
Good practice? Rather acceptable practice. It makes maintenance of tests a lot easier, and the code slightly clearer.
It definitely is not a limitation. When you write a unit test you don't really care what kind of exception is thrown. Outside of expected exceptions, any exception will result in a red bar telling you that something is not OK. Therefore it is sufficient to have a "catch all" throws Exception clause.
You don't have to throw Exception, and I would imaging that tool could have performed the static analysis to determine if a checked exception could have been thrown. However, when I write unit tests by hand I typically add the throw clause because invariably I add a line of code that does throw a checked exception.

Categories