I am trying my hand at writing test cases. From what I have read, my tests should fail from the start and I should strive to make tests pass. However, I find myself writing tests checking boundaries and the exceptions they should cause:
#Test(expected=NegativeArraySizeException.class)
public void testWorldMapIntInt() {
WorldMap w = new WorldMap(-1, -1);
}
#Test(expected=IndexOutOfBoundsException.class)
public void testGetnIntnInt() {
WorldMap w = new WorldMap(10,10);
Object o = w.get(-1, -1);
}
However, this test passes by default because Java will throw the exception anyway. Is there a better way to handle these kinds of expected exceptions, possibly a way that fails by default-- forcing me to strive to handle these cases?
I agree that the style you present is not so good. The problem is that it doesn't check where in the method the exception is thrown, so it's possible to get false negatives.
We usually write tests for exceptions like this:
public void testWorldMapIntInt() {
try {
WorldMap w = new WorldMap(-1, -1);
Assert.fail("should have thrown IndexOutOfBoundsException");
}
catch (IndexOutOfBoundsException e) {}
}
Expected behaviour for WorldMap is to throw an exception if (-1, -1) passed into it
Initially it doesn't do that, so your test will fail as it does not see expected exception.
You implement the code for WorldMap correctly, including throwing exception when (-1, -1) passed in.
You rerun your test, it passes.
Sound like good TDD to me!
That seems like a fair test to write. WorldMap is no standard Java class. Presumably it's your own class. Therefore the test wouldn't be passing if you hadn't already written some code. This test will force you to throw (or propagate) an appropriate exception from your class. That sounds like a good test to me, which you should write before implementing the behavior.
I personally look for mistakes like that in the WorldMap constructor and throw an IllegalArgumentException, that way you can provide a better error message, such as what the value passed in was and what the expected range is.
As for having that test fail by default, I cannot think of a reasonable way of doing that if you are going to have it actually do something (if you are writing the tests first then it should fail because the constructor won't have any code).
Agree with accepted answer, try-fail-catch idiom, although ugly and cluttering the test, is much better than #Test(expcted=...) as it might report false positives.
A while back I implemented very simple JUnit rule to deal with exception testing in both safe and readable manner:
public class DefaultFooServiceTest {
#UnderTest
private FooService fooService = new DefaultFooService();
#Rule
public ExceptionAssert exception = new ExceptionAssert();
#Test
public void shouldThrowNpeWhenNullName() throws Exception {
//given
String name = null;
//when
fooService.echo(name);
//then
exception.expect(NullPointerException.class);
}
#Test
public void shouldThrowIllegalArgumentWhenNameJohn() throws Exception {
//given
String name = "John";
//when
fooService.echo(name);
//then
exception.expect(IllegalArgumentException.class)
.expectMessage("Name: 'John' is not allowed");
}
}
See blog post and source.
Related
While refactoring Rultor to use Cactoos instead of Guava, I’m having an issue with negative tests of GithubProfileTest and GithubProfileValidationTest.
After the refactor, the positive test cases pass for both mentioned test classes, but the negative test cases that expect a particular exception fail.
The affected refactored code under test is GithubProfile.assets method and GithubProfile.asset method.
I refactored assets method to look like this:
public Map<String, InputStream> assets() throws IOException {
final XML xml = this.read();
final List<XML> nodes = xml.nodes("/p/entry[#key='assets']/entry");
return new MapOf<>(
new Mapped<>(
nodes,
input ->
new MapEntry<>(
input.xpath("#key").get(0),
this.asset(input.xpath("text()").get(0))
)
)
);
}
On different test cases the this.asset call is expected to throw Profile.ConfigException. Instead, upon calling the assets method, the test fails with a Unable to evaluate the expression Method threw 'java.io.UncheckedIOException' exception, and the Profile.ConfigException is simply ignored/hidden.
It seems that MapOf somehow fails to evaluate, or "hides", the exception that the call to this.asset method raised, raising itself an UncheckedIOException, so I'm unable to fix this and have the Profile.ConfigException raised.
When debugging, the UncheckedIOException doesn't contain any info whatsoever of a Profile.ConfigException being raised.
Any hints on why I might be getting this behaviour or possible solutions?
The problem is that Iterable#next() (in JDK) doesn't allow to throw checked exceptions (like Profile.ConfigException). That's why org.cactoos.iterator.Mapped catches them all and throws UncheckedIOException instead. It's unfixable, thanks to JDK design. The best you can do is good old for loop:
public Map<String, InputStream> assets() throws IOException {
final XML xml = this.read();
final List<XML> nodes = xml.nodes("/p/entry[#key='assets']/entry");
final List<MapEntry> entries = new LinkedList<>();
for (final XML node : nodes) {
entries.add(
new MapEntry<>(
input.xpath("#key").get(0),
this.asset(input.xpath("text()").get(0)) // checked exeption here
)
);
}
return new MapOf<>(entries);
}
The reason is probably the conversion done in org.cactoos.func.UncheckedFunc while iterating to populate the map.
Since functional style programming usually does not play very well with exceptions, the API tries to avoid declaring checked exceptions. So you probably have to live with that.
Now this is really quite difficult for me to explain so please bear with me.
I've been wondering as of late the best way to "unwind" every chained method back to a main method when certain circumstances are met. For example, say I make a call to a method from Main and from that method I call another one and so on. At some point I may want to cancel all further operations of every method that is chained and simply return to the Main method. What is the best way to do this?
I'll give a scenario:
In the following code there are 3 methods, however when Method1 calls Method2 with a null value it should unwind all the way back to Main without further operations in Method2 (EG the "Lots of other code" section).
public static void main(String[] args)
{
try
{
Method1();
}
catch( ReturnToMainException e )
{
// Handle return \\
}
}
public static void Method1() throws ReturnToMainException
{
String someString = null;
Method2( someString );
// Lots more code after here
}
public static boolean Method2( String someString )
{
if( someString == null )
throw new ReturnToMainException();
else if( someString.equals( "Correct" ))
return true;
else
return false;
}
In this example I use a throw which I've read should only be used in "Exceptional Circumstances". I often run into this issue and find myself simply doing If/Else statements to solve the issue, but when dealing with methods that can only return True/False I find I don't have enough options to return to decide on an action. I guess I could use Enumerators or classes but that seems somewhat cumbersome.
I use a throw which I've read should only be used in "Exceptional Circumstances". I often run into this issue and find myself simply doing If/Else statements to solve the issue
Exception throwing is relatively expensive so it should not be used without careful thought but I believe that your example is a ok example of proper usage.
In general, you should use exceptions only for "exceptional" behavior of the program. If someString can be null through some sort of user input, database values, or other normal mechanism then typically you should handle that case with normal return mechanisms if possible.
In your case, you could return a Boolean object (not a primitive) and return null if someString is null.
private static Boolean method2( String someString ) {
if (someString == null) {
return null;
}
...
}
Then you would handle the null appropriately in the caller maybe returning a boolean to main based on whether or not the method "worked".
private static boolean method1() {
...
Boolean result = method2(someString);
if (result == null) {
// the method didn't "work"
return false;
}
Then in main you can see if method1 "worked":
public static void main(String[] args) {
if (!method1()) {
// handle error
}
...
}
Notice that I downcased your method names and changed the permissions of your methods to private both which are good patterns.
Enumerators or classes but that seems somewhat cumbersome.
Yeah indeed. It depends a bit on how this code is used. If it is a API method that is called by others, you might want to return some sort of Result class which might provide feedback like a boolean that the argument was null. Or you might throw an IllegalArgumentException in that case. Instead, if this is an internal local private method, then I'd vote for a simpler way of handling argument errors. Either way I'd use javadocs to document the behavior so you don't trip up future you.
Hope this helps.
I have set up some JUnit (4.12) test with the ExpectedException feature, and I would like the test to continue after the expected exception. But I never see the log '3', as the execution seems to stop after the exception, event if catch?
Is this actually possible, and how?
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testUserAlreadyExists() throws Exception {
log.info("1");
// Create some users
userService.createUser("toto1");
userService.createUser("toto2");
userService.createUser("toto3");
Assert.assertTrue( userService.userExists("toto1") );
Assert.assertTrue( userService.userExists("toto2") );
Assert.assertTrue( userService.userExists("toto3") );
log.info("2");
// Try to create an existing user
exception.expect(AlreadyExistsException.class);
userService.createUser("toto1");
log.info("3");
}
You cannot do that, when the exception is thrown it's thrown for real, ExpectedException rule or not.
If you really want this kind of behaviour, you can go back to the "old school" pattern:
try {
userService.createUser("toto1");
Assert.fail("expecting some AlreadyExistsException here")
} catch (AlreadyExistsException e) {
// ignore
}
log.info("3");
But I wouldn't bother for some log.
This SO solution seems to do what you want to do: JUnit continue to assert things after expected exception
I myself was thinking something similar. To continue with the test, you would have to catch the exception yourself in the test. This solution shows an elegant way of doing that.
Note: If you make a rule to expect an exception (as you did), the test will return successful as soon as that exception is thrown.
Reference: http://junit.org/javadoc/latest/org/junit/rules/ExpectedException.html
If you don't want to add a lot of similar test methods for something that has many options to throw the expected exception and want to verify that it actually throws on all of the desired cases within a single unit-test instead, I'd suggest this (not pretty maybe) helpful schema:
#Test
public void testThatSomethingExpectedlyFails() {
for (int i = 1; i <= 3; i++) {
try {
switch (i) {
case 1: // smth here throws the exception when configuration #1;
case 2: // smth here throws the exception when configuration #2;
case 3: // smth here throws the exception when configuration #3;
}
} catch (ExceptionThatIsExpected expected) {
continue;
} catch (Exception unexpected) {
/* the test must fail when an unexpected exception is thrown */
fail("The test has failed due to an unexpected exception: " + unexpected.getMessage()); // or just re-throw this exception
}
/* the test must fail when a case completes without the expected exception */
fail("No expected exception occurred at case " + i);
}
}
The one could also iterate items (and even execute functions) of some preliminarily prepared list instead of switch-case with hard-coded integers.
First of all your test doesn't test one thing. It tests "userExists" and "createUser" under different conditions a.k.a. different scenarios. This is called an AssertionRoulette. You wouldn't need a hack to continue to log "3", if you would write tests, that fail fo the right reason.
If the tests fail for the right reason, you can see the scenario why it fails without doing all the logging stuff. The Junit-Runner does the logging for you already.
#Test
public void testUserExists_UserCreatedUserNotExistent_expectTrue()
{
// Create some users
userService.createUser("toto1");
// Assert That user exists
Assert.assertTrue( userService.userExists("toto1") );
}
#Test
public void testCreateUser_UserAlreadyCreated_expectAlreadyExistsExceptionIsThrown()
{
// Create some users
userService.createUser("toto1");
// Try to create an existing user
exception.expect(AlreadyExistsException.class);
userService.createUser("toto1");
}
I have the following code:
TestClass test=new TestClass();
test.setSomething1(0); //could, but probably won't throw Exception
test.setSomething2(0); //could, but probably won't throw Exception
I would like to execute: test.setSomething2(0); even if test.setSomething(0) (the line above it) throws an exception. Is there a way to do this OTHER than:
try{
test.setSomething1(0);
}catch(Exception e){
//ignore
}
try{
test.setSomething2(0);
}catch(Exception e){
//ignore
}
I have a lot of test.setSomething's in a row and all of them could throw Exceptions. If they do, I just want to skip that line and move to the next one.
For clarification, I don't care if it throws an Exception, and I can't edit the source code of the code which throws this exception.
THIS IS A CASE WHERE I DON'T CARE ABOUT THE EXCEPTIONS (please don't use universally quantified statements like "you should never ignore Exceptions"). I am setting the values of some Object. When I present the values to a user, I do null checks anyway, so it doesn't actually matter if any of the lines of code execute.
try {
// Your code...
} catch (Exception ignore) { }
Use the word ignore after the Exception keyword.
There is no way to fundamentally ignore a thrown exception. The best that you can do is minimize the boilerplate you need to wrap the exception-throwing code in.
If you are on Java 8, you can use this:
public static void ignoringExc(RunnableExc r) {
try { r.run(); } catch (Exception e) { }
}
#FunctionalInterface public interface RunnableExc { void run() throws Exception; }
Then, and implying static imports, your code becomes
ignoringExc(() -> test.setSomething1(0));
ignoringExc(() -> test.setSomething2(0));
IntelliJ Idea IDE suggests to rename a variable to ignored
when it isn't used.
This is my sample code.
try {
messageText = rs.getString("msg");
errorCode = rs.getInt("error_code");
} catch (SQLException ignored) { }
Unfortunately no, there isn't, and this is by intention. When used correctly, exceptions should not be ignored as they indicate that something didn't work and that you probably shouldn't continue down your normal execution path. Completely ignoring exceptions is an example of the 'Sweep it under the rug' anti-pattern, which is why the language doesn't support doing so easily.
Perhaps you should look at why TestClass.setSomething is throwing exceptions. Is whatever you're trying to 'test' really going to be valid if a bunch of setter methods didn't work correctly?
You can't ignore exception in Java. If a method declares being able to throw something this is because something important can't be done, and the error can't be corrected by the method designer. So if you really wan't to simplify your life encapsulate the method call in some other method like this :
class MyExceptionFreeClass {
public static void setSomething1(TestClass t,int v) {
try {
t.setSomething1(v);
} catch (Exception e) {}
public static void setSomething2(TestClass t,int v) {
try {
t.setSomething2(v);
} catch (Exception e) {}
}
and call it when you need it:
TestClass test=new TestClass();
MyExceptionFreeClass.setSomething1(test,0);
MyExceptionFreeClass.setSomething2(test,0);
You should not ignore Exceptions. You should handle them. If you want to make your test code simple, then add the try-catch block into your functions. The greatest way to ignore exceptions is to prevent them by proper coding.
I know this is old, but I do think there are occasions when you want to ignore an exception. Consider you have a string that contains a delimited set of parts to be parsed. But, this string can sometimes contain say, 6 or 7 or 8 parts. I don't feel that checking the len each time in order to establish an element exists in the array is as straight forward as simply catching the exception and going on. For example, I have a string delimited by '/' character that I want to break apart:
public String processLine(String inLine) {
partsArray = inLine.split("/");
//For brevity, imagine lines here that initialize
//String elems[0-7] = "";
//Now, parts array may contains 6, 7, or 8 elements
//But if less than 8, will throw the exception
try {
elem0 = partsArray[0];
elem1 = partsArray[1];
elem2 = partsArray[2];
elem3 = partsArray[3];
elem4 = partsArray[4];
elem5 = partsArray[5];
elem6 = partsArray[6];
elem7 = partsArray[7];
catch (ArrayIndexOutOfBoundsException ignored) { }
//Just to complete the example, we'll append all the values
//and any values that didn't have parts will still be
//the value we initialized it to, in this case a space.
sb.append(elem0).append(elem1).append(elem2)...append(elem7);
//and return our string of 6, 7, or 8 parts
//And YES, obviously, this is returning pretty much
//the same string, minus the delimiter.
//You would likely do things to those elem values
//and then return the string in a more formatted way.
//But was just to put out an example where
//you really might want to ignore the exception
return sb.toString();
}
Those who write empty catch blocks shall burn in the Hell for the eternity.
Or worse, they will be forced to debug the damn rubbish they wrote forever and ever.
That said, one thing you might want to do is writing exception handling in a less verbose way. The NoException library is very good at that.
I'm pretty new to JUnit, and I don't really know what best practices are for exceptions and exception handling.
For example, let's say I'm writing tests for an IPAddress class. It has a constructor IPAddress(String addr) that will throw an InvalidIPAddressException if addr is null. As far as I can tell from googling around, the test for the null parameter will look like this.
#Test
public void testNullParameter()
{
try
{
IPAddress addr = new IPAddress(null);
assertTrue(addr.getOctets() == null);
}
catch(InvalidIPAddressException e)
{
return;
}
fail("InvalidIPAddressException not thrown.");
}
In this case, try/catch makes sense because I know the exception is coming.
But now if I want to write testValidIPAddress(), there's a couple of ways to do it:
Way #1:
#Test
public void testValidIPAddress() throws InvalidIPAddressException
{
IPAddress addr = new IPAddress("127.0.0.1");
byte[] octets = addr.getOctets();
assertTrue(octets[0] == 127);
assertTrue(octets[1] == 0);
assertTrue(octets[2] == 0);
assertTrue(octets[3] == 1);
}
Way #2:
#Test
public void testValidIPAddress()
{
try
{
IPAddress addr = new IPAddress("127.0.0.1");
byte[] octets = addr.getOctets();
assertTrue(octets[0] == 127);
assertTrue(octets[1] == 0);
assertTrue(octets[2] == 0);
assertTrue(octets[3] == 1);
}
catch (InvalidIPAddressException e)
{
fail("InvalidIPAddressException: " + e.getMessage());
}
}
Is is standard practice to throw unexpected exceptions to JUnit or just deal with them yourself?
Thanks for the help.
Actually, the old style of exception testing is to wrap a try block around the code that throws the exception and then add a fail() statement at the end of the try block. Something like this:
public void testNullParameter() {
try {
IPAddress addr = new IPAddress(null);
fail("InvalidIPAddressException not thrown.");
} catch(InvalidIPAddressException e) {
assertNotNull(e.getMessage());
}
}
This isn't much different from what you wrote but:
Your assertTrue(addr.getOctets() == null); is useless.
The intend and the syntax are clearer IMO and thus easier to read.
Still, this is a bit ugly. But this is where JUnit 4 comes to the rescue as exception testing is one of the biggest improvements in JUnit 4. With JUnit 4, you can now write your test like this:
#Test (expected=InvalidIPAddressException.class)
public void testNullParameter() throws InvalidIPAddressException {
IPAddress addr = new IPAddress(null);
}
Nice, isn't it?
Now, regarding the real question, if I don't expect an exception to be thrown, I'd definitely go for way #1 (because it's less verbose) and let JUnit handle the exception and fail the test as expected.
For tests where I don't expect an exception, I don't bother to catch it. I let JUnit catch the exception (it does this reliably) and don't cater for it at all beyond declaring the throws cause (if required).
I note re. your first example that you're not making use of the #expected annotation viz.
#Test (expected=IndexOutOfBoundsException.class) public void elementAt() {
int[] intArray = new int[10];
int i = intArray[20]; // Should throw IndexOutOfBoundsException
}
I use this for all tests that I'm testing for throwing exceptions. It's briefer than the equivalent catch/fail pattern that I had to use with Junit3.
Since JUnit 4.7 you have the possibility to use an ExpectedException rule and you should use it. The rule gives you the possibility to define exactly the called method where the exception should be thrown in your test code. Moreover, you can easily match a string against the error message of the exception. In your case the code looks like this:
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
public void test() {
//working code here...
expectedException.expect(InvalidIPAddressException.class);
IPAddress addr = new IPAddress(null);
}
UPDATE: In his book Practical Unit Testing with JUnit and Mockito Tomek Kaczanowski argues against the use of ExpectedException, because the rule "breaks the arrange/act/assert [...] flow" of a Unit test (he suggests to use Catch Exception Library instead). Although I can understand his argument, I think using the rule is fine if you do not want to introduce another 3rd-party library (using the rule is better than catching the exception "manually" anyway).
For the null test you can simply do this:
public void testNullParameter() {
try {
IPAddress addr = new IPAddress(null);
fail("InvalidIPAddressException not thrown.");
}
catch(InvalidIPAddressException e) { }
}
If the exception has a message, you could also check that message in the catch if you wish. E.g.
String actual = e.getMessage();
assertEquals("Null is not a valid IP Address", actual);
For the valid test you don't need to catch the exception. A test will automatically fail if an exception is thrown and not caught. So way #1 would be all you need as it will fail and the stack trace will be available to you anyway for your viewing pleasure.
if i understand your question, the answer is either - personal preference.
personally i throw my exceptions in tests. in my opinion a test failing by assertion is equivalent to a test failing by an uncaught exception. both show something that needs to be fixed.
the important thing to remember in testing is code coverage.
In general way #1 is the way to go, there is no reason to call out a failure over an error - either way the test essentially failed.
The only time way #2 makes sense if you need a good message of what went wrong, and just an exception won't give that to you. Then catching and failing can make sense to better announce the reason of the failure.
Reg: Testing for Exceptions
I agree with "Pascal Thivent", ie use #Test (expected=InvalidIPAddressException.class)
Reg: Testing for testValidIPAddress
IPAddress addr = new IPAddress("127.0.0.1");
byte[] octets = addr.getOctets();
I would write a test like
class IPAddressTests
{
[Test]
public void getOctets_ForAValidIPAddress_ShouldReturnCorrectOctect()
{
// Test code here
}
}
The point is when testinput is VALID ipAddress
The test must be on the public methods/capabilities on the class asserting that they are working as excepted
IMO it is better to handle the exception and show appropriate messaging from the test than throwing it from a test.