Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spock - Testing Exceptions with Data Tables

How can exceptions be tested in a nice way (e.g. data tables) with Spock?

Example: Having a method validateUser that can throw exceptions with different messages or no exception if the user is valid.

The specification class itself:

class User { String userName }  class SomeSpec extends spock.lang.Specification {      ...tests go here...      private validateUser(User user) {         if (!user) throw new Exception ('no user')         if (!user.userName) throw new Exception ('no userName')     } } 

Variant 1

This one is working but the real intention is cluttered by all the when / then labels and the repeated calls of validateUser(user).

    def 'validate user - the long way - working but not nice'() {         when:         def user = new User(userName: 'tester')         validateUser(user)          then:         noExceptionThrown()          when:         user = new User(userName: null)         validateUser(user)          then:         def ex = thrown(Exception)         ex.message == 'no userName'          when:         user = null         validateUser(user)          then:         ex = thrown(Exception)         ex.message == 'no user'     } 

Variant 2

This one is not working because of this error raised by Spock at compile time:

Exception conditions are only allowed in 'then' blocks

    def 'validate user - data table 1 - not working'() {         when:         validateUser(user)          then:         check()          where:         user                         || check         new User(userName: 'tester') || { noExceptionThrown() }         new User(userName: null)     || { Exception ex = thrown(); ex.message == 'no userName' }         null                         || { Exception ex = thrown(); ex.message == 'no user' }     } 

Variant 3

This one is not working because of this error raised by Spock at compile time:

Exception conditions are only allowed as top-level statements

    def 'validate user - data table 2 - not working'() {         when:         validateUser(user)          then:         if (expectedException) {             def ex = thrown(expectedException)             ex.message == expectedMessage         } else {             noExceptionThrown()         }          where:         user                         || expectedException | expectedMessage         new User(userName: 'tester') || null              | null         new User(userName: null)     || Exception         | 'no userName'         null                         || Exception         | 'no user'     } 
like image 504
René Scheibe Avatar asked Oct 04 '13 15:10

René Scheibe


1 Answers

The recommended solution is to have two methods: one that tests the good cases, and another that tests the bad cases. Then both methods can make use of data tables.

Example:

class SomeSpec extends Specification {      class User { String userName }      def 'validate valid user'() {         when:         validateUser(user)          then:         noExceptionThrown()          where:         user << [                 new User(userName: 'tester'),                 new User(userName: 'joe')]     }      def 'validate invalid user'() {         when:         validateUser(user)          then:         def error = thrown(expectedException)         error.message == expectedMessage          where:         user                     || expectedException | expectedMessage         new User(userName: null) || Exception         | 'no userName'         new User(userName: '')   || Exception         | 'no userName'         null                     || Exception         | 'no user'     }      private validateUser(User user) {         if (!user) throw new Exception('no user')         if (!user.userName) throw new Exception('no userName')     }  } 
like image 151
Peter Niederwieser Avatar answered Sep 25 '22 21:09

Peter Niederwieser