Test With Spring Course
Save Time by Writing Less Test Code
  • Home
  • Pre-Sales FAQ
  • Support
  • Log In

/ July 8, 2017 / petrikainulainen

Writing Assertions With Spock Framework

Lesson Progress:
← Back to Topic

After we have finished this lesson, we:

  • Know how we can add conditions to our feature methods.
  • Can write assertions for the exceptions thrown by the system under specification.
  • Know how we can use Hamcrest matchers.

This lesson assumes that:

  • You are familiar with Spock Specifications
  • You can create feature methods

Watch the Lesson

 

The text version of this lesson is given in the following:

Introduction to Assertions (aka Conditions)

One difference between Spock Framework and JUnit is that Spock framework doesn’t provide an assertion API. Instead, we can specify the expected state by using conditions. We can write conditions by following these rules:

  • We have to specify the expected state in the then or expect block.
  • We can create conditions by using boolean expressions. To be more specific, we can use any expression and Groovy decides whether our expression is true or false.
  • If our condition is true, our test will pass.
  • If our condition is false, our test will fail.

If we want to specify conditions outside of the then and expect blocks, we have to use the assert keyword.

Additional Reading:

  • Groovy Language Specification – Semantics: 5. The Groovy Truth


We can now create conditions with Spock Framework. Before we will put our new skills into practice, we will take a look at two rules which help us to write feature methods that are easy to read:

  • We should add the most important conditions to the beginning of the then or expect block and provide a good description to these conditions.
  • If our conditions belong to different logical groups, we should divide our then or expect block into different sections by using the and label. When we do this, we must provide a good description to the created sections.

Next, we will find out how we can add new conditions to the then and expect blocks.

Writing Assertions in the Then and Expect Blocks

As we already know, we can write assertions by adding new conditions to the then or expect block of our feature method. Let’s take a look at two examples that demonstrate how we can add conditions to our feature methods.

First, let’s write two conditions which verify that our feature method creates an empty list. We can do this by adding a then block to our feature method and adding our conditions to that block.

After we have added a then block to our feature method, the source code of our specification class looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(UnitTest.class)
class SimpleConditionSpec extends Specification {

    def 'Write an assertion in the then block'() {

        when: 'We create a new list'
        def list = []

        then: 'Should create an empty list'
        list.isEmpty()
        list.size() == 0
    }
}

By the way, we don’t need both of these conditions. I used these conditions here because I wanted to demonstrate that we can use the return value of a method as a condition or specify the condition by using logical operators.

Second, let’s verify that the max() method of the Math class returns the greater of two numbers. We can do this by adding a new expect block to our feature method and adding our condition to that block.

After we have added a new expect block to our feature method, the source code of our specification class looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(UnitTest.class)
class SimpleConditionSpec extends Specification {

    def 'Write an assertion in the expect block'() {

        expect: 'Should return the bigger number'
        Math.max(1, 2) == 2
    }
}

Additional Reading:

  • Spock Primer: Conditions

Let’s move on and find out how we can write assertions for the exceptions thrown by the system under specification.

Writing Assertions for Exceptions

When we want to verify that the when block of our feature method throws an exception, we have to use exception conditions. Next, we will take a look at three examples which demonstrate how we can write assertions for the exceptions thrown by the system under specification.

First, if we want to verify that the when block of our feature method throws a specific exception, we have to use the thrown() method and pass the type of the expected exception as a method parameter.

Let’s write a condition which verifies that the Stack class throws the EmptyStackException if we try to pop an empty stack. After we have written this condition, the source code of our feature method looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(UnitTest.class)
class ExceptionConditionSpec extends Specification {

    def stack = new Stack()

    def 'Verify that exception is thrown'() {

        when: 'We try to remove an element from an empty stack'
        stack.pop()

        then: 'Should throw an exception'
        thrown EmptyStackException
    }
}

Second, if we want to verify that the when block of our feature method doesn’t throw a specific exception, we have to use the notThrown() method and pass the type of the exception as a method parameter.

Let’s write a condition which verifies that the Stack class doesn’t throw the EmptyStackException if we try to pop a stack that has one item. After we have written this condition, the source code of our feature method looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(UnitTest.class)
class ExceptionConditionSpec extends Specification {

    def stack = new Stack()

    def 'Verify that exception is not thrown'() {

        given: 'The stack has one item'
        stack.push('Hello world!')

        when: 'We remove an element from the stack'
        stack.pop()

        then: 'Should not throw an exception'
        notThrown EmptyStackException
    }
}

Third, sometimes we want to write additional assertions for the thrown exception or we want to verify that the state of the system under specification is correct. Spock Framework supports both use cases because exception conditions can be followed by other conditions and other blocks.

Let’s ensure that our when block throws a RuntimeException that has the correct message. We can write the required conditions by following these steps:

  1. Verify that our when block throws a RuntimeException and get a reference to the thrown exception object.
  2. Ensure that the thrown exception has the correct message.

After we have written the required conditions, the source code of our specification class looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(UnitTest.class)
class ExceptionConditionSpec extends Specification {

    def 'Write assertions for the thrown exception'() {

        when: 'A RuntimeException is thrown with a message'
        throw new RuntimeException('Hello World!')

        then: 'Should throw RuntimeException with the correct message'
        def ex = thrown RuntimeException
        ex.message == 'Hello World!'
    }
}

Additional Reading:

  • Spock Primer: Exception Conditions

Next, we will find out how we can use Hamcrest matchers.

Using Hamcrest Matchers

Spock Framework allows us to specify conditions by using Hamcrest matchers. This is a good thing because it helps us to write conditions that are easy read, write, and maintain. When we want to write conditions by using a Hamcrest matcher, we have to use this format:

[object or value] [the used Hamcrest matcher]

Let’s verify that our feature method creates a list that has one item. We can write the required conditions by following these steps:

  1. Verify that the created list has one item.
  2. Ensure that the created list contains the correct item.

After we have written the required conditions, the source code of our feature method looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

import static org.hamcrest.Matchers.contains
import static org.hamcrest.Matchers.hasSize

@Category(UnitTest.class)
class HamcrestConditionSpec extends Specification {

    def 'Write assertions with Hamcrest matchers'() {

        given: 'We create a new list'
        def list = []

        when: 'A new item is added to the list'
        list.add('Hello World!')

        then: 'The list should have one item'
        list hasSize(1)

        and: 'The list should contain the correct item'
        list contains('Hello World!')
    }
}

We can now add conditions to our feature methods, write assertions for the thrown exceptions, and specify conditions by using Hamcrest matchers.

Let’s summarize what we learned from this lesson.

Summary

This lesson has taught us five things:

  • We should specify our conditions by using boolean expressions in the then or expect blocks.
  • We should add the most important conditions to the beginning of the then or expect block.
  • If our conditions belong to different logical groups, we should divide our block into different sections by using the and label.
  • Exception conditions can be followed by other conditions and other blocks.
  • If we want to use Hamcrest matchers, we have to specify our conditions by using the format: [object or value] [the used Hamcrest matcher].

Get the source code from Github

← Previous Lesson Next Lesson →

Can I help you?

This is a free sample lesson of my Test With Spring course. If this lesson helped you to solve your problem, you should find out how my testing course can help you.

Support and Privacy

  • Pre-Sales FAQ
  • Support
  • Cookie Policy
  • No Bullshit Privacy Policy
  • No Bullshit Terms and Conditions

Test With Spring Course

  • Starter Package
  • Intermediate Package
  • Master Package

Free Sample Lessons

  • Introduction to JUnit 4
  • Introduction to Unit Testing
  • Introduction to Integration Testing
  • Introduction to End-to-End Testing
  • Introduction to Spock Framework
  • Introduction to Integration Testing – Spock Edition
  • Writing End-to-End Tests With Spock Framework

Copyright Koodikupla Oy 2016 — Built on Thesis by Themedy