Over a million developers have joined DZone.

Spocklight: Custom Default Responses for Stubs

Spock has found great popularity in the BDD crowd over the last few years. Take a look at this hands-on example of stubbing in the popular framework.

· DevOps Zone

The DevOps zone is brought to you in partnership with Sonatype Nexus. The Nexus suite helps scale your DevOps delivery with continuous component intelligence integrated into development tools, including Eclipse, IntelliJ, Jenkins, Bamboo, SonarQube and more. Schedule a demo today

Although I couldn't make it to Gr8Conf EU this year, I am glad that a lot of the presentations are available as slide decks and videos. The slide deck for the talk Interesting nooks and crannies of Spock you (may) have never seen before by Marcin ZajÄ…czkowski is very interesting. This is really a must-read if you use Spock (and why shouldn't you?) in your projects. One of the interesting things is the ability to change the response for methods in a class that is stubbed using Spock's Stub method, but that have no explicit stubbed method definition.

When we create a stub, we normally add code that implements the methods from the stubbed class. In our specification, the methods we have written are invoked instead of the original methods from the stubbed class. By default, if we don't override a method definition, but it is used in the specification, Spock will try to create a response using a default response strategy. The default response strategy for a stub is implemented by the class EmptyOrDummyResponse. For example, if a method has a return type Message , then Spock will create a new instance of Message and return it to be used in the specification. Spock also has a ZeroOrNullResponse response strategy. With this strategy, null is returned for our method, which returns the Message type.

Both response strategies implement the IDefaultResponse interface. We can write our own response strategy by implementing this interface. When we use the Stub method, we can pass an instance of our response strategy with the defaultResponse named argument of the method. An example: MessageProvider stub = Stub(defaultResponse: new CustomResponse()). We implement the respond method of IDefaultResponse to write a custom response strategy. The method gets an IMockInvocation instance. We can use this instance to check for example the method name, return type, arguments, and more. Based on this, we can write code to return the response we want.

In the following example we have a Spock specification where we create a stub using the default response strategy, the ZeroOrNullResponse strategy, and a custom-written response strategy:

package com.mrhaki.spock

import spock.lang.Specification
import spock.lang.Subject
import org.spockframework.mock.ZeroOrNullResponse
import org.spockframework.mock.IDefaultResponse
import org.spockframework.mock.IMockInvocation

class SampleSpec extends Specification {

    def """stub default response returns
           instance of Message created with default constructor"""() {
        given: 'Use default response strategy EmptyOrDummyResponse'
        final MessageProvider messageProvider = Stub()
        final Sample sample = new Sample(messageProvider)

        sample.sampleMessage == 'Sample says: default'

    def "stub default reponse returns null with ZeroOrNullResponse"() {
        given: 'Use default response strategy of ZeroOrNullResponse'
        final MessageProvider messageProvider =
                Stub(defaultResponse: ZeroOrNullResponse.INSTANCE)
        final Sample sample = new Sample(messageProvider)


        then: 'messageProvider.message returns null'

    def """stub default response returns
           Message object with initialized text property
           from StubMessageResponse"""() {
        given: 'Use custom default response strategy'
        final MessageProvider messageProvider =
                Stub(defaultResponse: new StubMessageResponse())
        final Sample sample = new Sample(messageProvider)

        sample.sampleMessage == 'Sample says: *STUB MESSAGE TEXT*'


 * Class to test with a dependency on MessageProvider
 * that is stubbed in the specification.
class Sample {
    private final MessageProvider messageProvider

    Sample(final MessageProvider messageProvider) {
        this.messageProvider = messageProvider

    String getSampleMessage() {
        "Sample says: ${messageProvider.message.text}"

    String sampleMessage(String prefix) {
        "Sample says: ${messageProvider.getMessageWithPrefix(prefix).text}"

 * Work with messages. This interface is stubbed
 * in the specification.
interface MessageProvider {
    Message getMessage()
    Message getMessageWithPrefix(String prefix)

 * Supporting class for MessageProvider.
class Message {
    String text = 'default'

 * Custom default response strategy.
 * When a method has a Message return type then we
 * create an instance of Message with a custom text
 * property value.
 * Otherwise rely on default behaviour.
class StubMessageResponse implements IDefaultResponse {
    Object respond(IMockInvocation invocation) {
        // If return type of method is Message we create
        // a new Message object with a filled text property.
        if (invocation.method.returnType == Message) {
            return new Message(text: '*STUB MESSAGE TEXT*')

        // Otherwise use default response handler for Stubs.
        return ZeroOrNullResponse.INSTANCE.respond(invocation)

Written with Spock 1.0-groovy-2.4.

The DevOps zone is brought to you in partnership with Sonatype Nexus. Use the Nexus Suite to automate your software supply chain and ensure you're using the highest quality open source components at every step of the development lifecycle. Get Nexus today


Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}