Unittesting with – Spock – What is Spock?



Unittesting with – Spock – What is Spock?

0 0


spock-training


On Github fpape / spock-training

 

Unittesting with

Spock

What is Spock?

written by Peter Niederwieser
unittesting framework providing a DSL in groovy
mocking framework
Compatible with JUnit: Run specifications with your IDE, build tool, and continuous integration server

Spocks basics

Specification

    class MyFirstSpecification extends Specification {
  // fields
  // fixture methods
  // feature methods
  // helper methods
}
  • if using maven: Rename MyFirstSpecification to MyFirstTest

Fields

    def obj = new ClassUnderSpecification()
@Shared
def res = new VeryExpensiveResource()
  • fields are initialized before each feature method
  • shared fiels are initialized once for all feature methods

Fixture Methods

    def setup() {}          // run before every feature method
def cleanup() {}        // run after every feature method
def setupSpec() {}     // run before the first feature method
def cleanupSpec() {}   // run after the last feature method
  • responsible for setting up and cleaning up the environment
  • setupSpec() and cleanupSpec() methods may not reference instance fields

Feature Methods

    def "pushing an element on the stack"() {
  // blocks go here
}
  • responsible for setting up and cleaning up the environment
  • setupSpec() and cleanupSpec() methods may not reference instance fields

blocks

  • setup
  • given
  • when
  • then
  • cleanup

basic usage

                def "pushing an element on the stack"() {
  given:
  def stack = new Stack()
  def elem = "push me"

  when:
  stack.push(elem)

  then:
  !stack.empty
  stack.size() == 1
  stack.peek() == elem
}
            

expect block

                def "test math max"() {
  when:
  def x = Math.max(1, 2)

  then:
  x == 2
}
            
                def "test math max"() {
  expect:
  Math.max(1, 2) == 2
}
            

then then then...

conditions

  • describe expected state cfr junit assertions
  • each line should contain boolean expression (according to groovy truth)
                then:
!stack.empty
stack.size() == 1
stack.peek() == elem
            

then then then...

exceptions

  • describe that a when block should throw an exception
  • each line should contain boolean expression (according to groovy truth)
                when:
stack.pop()

then:
notThrown(SomeFancyOtherExcpetion)
def e = thrown(EmptyStackException)
e.cause == null
stack.isEmpty()
            

where where where...

  • used for datadriven tests
                def "test math max"() {
  expect:
  Math.max(v1, v2) == ev

  where:
  v1 | v2 | ev
  1  | 1  | 1
  1  | 2  | 2
  2  | 1  | 1
}
            

where where where...

                def "test db"(String name, int age, String gender) {
  given:
  when:
  then:
  where:
  [name, age, gender] = sql.execute("""
       select name, age, sex from customer
     """)
}
            

Spock mocking

Creating mocks

    // "dynamic" style
def subscriber = Mock(Subscriber)
// "static" style
Subscriber subscriber = Mock()

Global vs. local interactions

    
given:
def subscriber = Mock(Subscriber)
// global interactions
subscriber.isAlive() >> true
when:
publisher.send(event)
then:
// local interactions
1 * subscriber.receive(event)

Optional vs. required interactions

                then:
// optional interactions
subscriber.isAlive() >> true
// required interactions
1 * subscriber.receive(event)
            

Optional interactions

  • don't have a cardinality
  • must have a return value

Required interactions

  • must have a cardinality
  • may have a return value

Cardinalities

                // exactly n times
n * subscriber.receive(event)
// at least n times
(n.._) * subscriber.receive(event)
// at most n times
(_..n) * subscriber.receive(event)
            

Argument constraints

                // no arguments
subscriber.receive()
// any argument
subscriber.receive(_)
// any non-null argument
subscriber.receive(!null)
// any argument equal to event
subscriber.receive(event)
// any argument not equal to event
subscriber.receive(!event)
// any argument that is-a Message (null is not allowed)
subscriber.receive(_ as Message)
// custom constraint
subscriber.receive( { it.priority >= 5 } )

// For methods that take multiple arguments:
// any argument
mock.foo(_, _, _)
// same as above
mock.foo(*_)
// any first arg, second arg non-null, third arg custom
mock.foo(_, !null, { it ==~ /a*b/ })
            

return values

                // single return value, repeated indefinitely
subscriber.isAlive() >> true
// multiple return values (anything that Groovy can iterate over),
// last one repeated indefinitely
subscriber.isAlive() >>> [true, false, true]
 // custom action
subscriber.isAlive() >> { throw new TimeoutException() }
// depending on arguments
subscriber.isEventSupported(_) >> { args[0] instanceof ... }
            

interactions the next level

                // no (more) method call on any mock
0 * _._
// interaction ordering
then:
1 * subscriber.isAlive() >> true
then:
1 * subscriber.isEventSupported(_) >> true
then:
1 * subscriber.receive(event)
            

Hands-on time