Creating simple tests in Spock Framework is easy. How could not it be? It is a test framework at the end of the day. A good tool should handle not only basic use cases but all real life scenarios. Last time I showed you how Spock supports testing methods arguments. Today, you will see how to create a test that expects a Java exception.
Method that throws exceptions
I have a class MyClass with one method strangeMethod that I would like to test.
public class MyClass {
public int strangeMethod(int selection) throws Exception {
switch (selection) {
case 0:
return 0;
case 1:
throw new NullPointerException();
case 2:
throw new ParseException("I don't know what happened.", 0);
default:
throw new Exception("Default exception");
}
}
}
The method takes a number as an input and based on it returns 0 or throws one of three exceptions: NullPointerException which is RuntimeException and two other that extends Exception.
Testing returned value
This is the simplest case possible. A test that verifies if 0 is returned when 0 is passed to the method may look like below.
class MyClassSpec extends Specification {
def "should strangeMethod return 0 when 0 is passed"() {
given:
MyClass myClass = new MyClass()
expect:
0 == myClass.strangeMethod(0)
}
}
In this case there are two sections: given and expect. The former is used to create an instance of the class that is being tested. The latter defines assertion which is expect 0 when 0 is provided.
Testing thrown exception
To test behaviour when a number 1 is passed, I can use thrown method from the Spock's Specification class.
def "should strangeMethod throw NullPointerException when 1 is passed"() {
given:
MyClass myClass = new MyClass()
when:
myClass.strangeMethod(1)
then:
thrown(NullPointerException)
}
This time given-when-then template is used. Given plays the same role as previously, when executes the method being tested and then defines expectation - an exception being thrown.
Expecting general exception
If I care only about a fact of throwing an exception but I do not rely on any specific exception, I can expect an instance of any class that extends Exception.
def "should strangeMethod throw any exception when 1 is passed"() {
given:
MyClass myClass = new MyClass()
when:
myClass.strangeMethod(1)
then:
thrown(Exception)
}
No matter if NullPointerException or ParseException or just Exception is thrown, the test will pass.
Expecting anything but exception
There is an antagonistic version of the thrown method - notThrown.
def "should strangeMethod not throw any exception when 0 is passed"() {
given:
MyClass myClass = new MyClass()
when:
myClass.strangeMethod(0)
then:
notThrown(Exception)
}
It is useful when you test a method that returns nothing and you want to test that it executes without throwing an exception.
Testing exception with test table
The strangeMethod is an excellent example to demonstrate usage of test table. I can check what types of exceptions are thrown from the method in one test.
def "should strangeMethod throw exceptions"() {
given:
MyClass myClass = new MyClass()
when:
myClass.strangeMethod(input)
then:
thrown(expectedException)
where:
input || expectedException
1 || NullPointerException
2 || ParseException
3 || Exception
}
The where section helps to define sets of test data. In this case when 1 is provided, NullPointerException is expected, for 2 - ParseException and for 3 - just an Exception.
I hope these few examples clearly show how to use Spock to test exceptions thrown from methods.