Elastic Lamb
Elastic Lamb

Reputation: 353

TDD with impossible exceptions

I have got a problem with TDD and impossible exceptions.

Let's say we have got a class named Foo (example):

Class Foo {
    public String getString(boolean shouldThrow) throws Exception {
        if(shouldThrow) throw new Exception();
        return "nonsense";
    }
}

Foo throws an exception only under certain circumstances (for simplicity i take a boolean here).

Now i want to create a class named Bar which reverses the string of Foo without throwing an exception.

Test:

class BarTest {
    public void testShouldReturnReversedStringOfBar() {
        Bar bar = new Bar();
        assertEquals("esnesnon", bar.getReversedString());
    }
}

I know that the boolean is false all the time. So the method getReversedString() will never throw an exception. But since it throws no exception, I can't write an assert which leads me to write the try/catch block inside of Bar.

So the Test will look like this:

class BarTest {
    public void testShouldReturnReversedStringOfBar() {
        Bar bar = new Bar();
        try {
            assertEquals("esnesnon", bar.getReversedString());
        } catch (Exception e) {
            // ... will never happen
        }
    }
}

But that is bad, because the exception will never happen and I have to write the try/catch-block every time I use the getReversedString() method. So I want the class like this:

class Bar {
    public String getReversedString() {
        Foo foo = new Foo();
        try {
            String s = foo.getString(false);
        } catch (Exception e) {
            // will never happen...
        }
        // ... reverse string ...
        return reversedString;
    }
}

But since the exception will never happen, I can't write a test for that try/catch-block - so I can't write the try/catch-block inside of Bar because TDD says "only write code if the lights are red".

It is a doom loop...

I hope you got me! Thanks!!

Upvotes: 0

Views: 481

Answers (3)

fge
fge

Reputation: 121710

Make the test itself throw the exception:

public void testShouldReturnReversedStringOfBar() 
    throws Exception
{
    Bar bar = new Bar();

    assertEquals("esnesnon", bar.getReversedString());
}

If an exception is thrown then the test will be marked as an error; which is "a failure but not as we know it, Jim" -- that fails anyway.


and by the way, throwing Exception is bad practice; when you catch Exception you also get to catch all RuntimeExceptions, that is, all unchecked exceptions as well. Don't do that.

Upvotes: 4

Illyes Istvan
Illyes Istvan

Reputation: 579

You could either add a throws declaration to the test method as fge already suggested, or you could consider re-designing your code by splitting your if into two separate methods (one that throws exception and one that doesn't)

class Foo {

    public String getStringWithException() throws Exception {
        // return data or throw exception if something goes wrong
    }

    public String getStringWithoutException() {
        // return data
    }

}

Upvotes: 0

chengpohi
chengpohi

Reputation: 14217

The TDD is a way to help you verify your program can work correctly. Though the Exception will never occur. I think you can throw Exception in junit test method. Just like:

public void testShouldReturnReversedStringOfBar() throw Exception{
    ....
}

Upvotes: 0

Related Questions