Using Mocks And stubs

Mocks And Stubs Returning Sequence of Values

Creating and working with mocks and stubs in Spock is easy. If we want to interact with our mocks and stubs we have several options to return values. One of the options is the triple right shift operator >>>. With this operator we can define different return values for multiple invocations of the stubbed or mocked method. For example we can use the >>> operator followed by a list of return values ['abc', 'def', 'ghi']. On the first invocation abc is return, the second invocation returns def and the third (and following) invocation(s) return ghi.

In the following specification we have a class under test StringUtil. The class has a dependency on an implementation of the Calculator interface. We mock this interface in our specification. We expect the calculateSize method is invoked 5 times, but we only provide 3 values for the invocations. This means the first time 1 is used, the second time 3 is used and the remaining invocations get the value 4:

package com.mrhaki.spock

@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
import spock.lang.Specification
import spock.lang.Subject

class SampleSpec extends Specification {

    @Subject
    def util = new StringUtil()

    def "Calculate sizes of String values"() {
        given:
        def calculator = Mock(Calculator)
        util.calculator = calculator

        when:
        def total = util.size('one', 'two', 'three', 'four', 'five')

        then:
        5 * calculator.calculateSize(_) >>> [1,3,4]

        total == 1 + 3 + 4 + 4 + 4
    }

}

class StringUtil {
    def calculator

    int size(final String[] s) {
        s.sum { calculator.calculateSize(it) }
    }
}

interface Calculator {
    int calculateSize(final String s)
}

Written with Spock 1.0-groovy-2.4.

Original post written on September 21, 2015

Change Return Value of Mocked or Stubbed Service Based On Argument Value

My colleague Albert van Veen wrote a blog post about Using ArgumentMatchers with Mockito. The idea is to let a mocked or stubbed service return a different value based on the argument passed into the service. This is inspired me to write the same sample with Spock.

Spock already has built-in mock and stub support, so first of all we don’t need an extra library to support mocking and stubbing. We can easily create a mock or stub with the Mock() and Stub() methods. We will see usage of both in the following examples.

In the first example we simply return true or false for ChocolateService.doesCustomerLikesChocolate() in the separate test methods.

import spock.lang.*

public class CandyServiceSpecification extends Specification {

    private ChocolateService chocolateService = Mock()
    private CandyService candyService = new CandyServiceImpl()
 
    def setup() {
        candyService.chocolateService = chocolateService
    }

    def "Customer Albert really likes chocolate"() {
        given:
        final Customer customer = new Customer(firstName: 'Albert')

        and: 'Mock returns true'
        1 * chocolateService.doesCustomerLikesChocolate(customer) >> true
        
        expect: 'Albert likes chocolate'
        candyService.getCandiesLikeByCustomer(customer).contains Candy.CHOCOLATE
    }

    def "Other customer do not like chocolate"() {
        given:
        final Customer customer = new Customer(firstName: 'Any other firstname')

        and: 'Mock returns false'
        1 * chocolateService.doesCustomerLikesChocolate(customer) >> false
        
        expect: 'Customer does not like chocolate'
        !candyService.getCandiesLikeByCustomer(customer).contains(Candy.CHOCOLATE)
    }

}

In the following example we mimic the ArgumentMatcher and this time we use a stub instead of mock.

import spock.lang.*

public class CandyServiceSpecification extends Specification {

    private CandyService candyService = new CandyServiceImpl()
 
    def setup() {
        candyService.chocolateService = Stub(ChocolateService) {
            getCandiesLikeByCustomer(_) >> { Customer customer ->
                customer?.firstName == 'Albert'
            }
        }
    }

    def "Customer Albert really likes chocolate"() {
        given:
        final Customer customer = new Customer(firstName: 'Albert')
        
        expect: 'Albert likes chocolate'
        candyService.getCandiesLikeByCustomer(customer).contains Candy.CHOCOLATE
    }

    def "Other customer do not like chocolate"() {
        given:
        final Customer customer = new Customer(firstName: 'Any other firstname')
        
        expect: 'Customer does not like chocolate'
        !candyService.getCandiesLikeByCustomer(customer).contains(Candy.CHOCOLATE)
    }

}

Code written with Spock 0.7-groovy-2.0

Original post written on May 17, 2013

Custom Default Responses for Stubs

Although I couldn't make it to Gr8Conf EU this year, I am glad 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 have no explicit stubbed method definition.

So normally when we create a stub we would 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 that 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. For example: MessageProvider stub = Stub(defaultResponse: new CustomResponse()). We implement the respond\ method of IDefaultResponse to write a custom response strategy. The method gets a 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

@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
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)

        expect:
        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)

        when:
        sample.sampleMessage

        then: 'messageProvider.message returns null'
        thrown(NullPointerException)
    }

    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)

        expect:
        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 {
    @Override
    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.

Original post written on September 16, 2016

Using Mock Method Arguments in Response

When we mock or stub methods we can use the method arguments passed to the method in the response for the mocked or stubbed method. We must write a closure after the rightShift operator (>>) and the closure arguments will resemble the arguments of the mocked or stubbed method. Alternatively we can use a single non-typed argument in the closure and this will contains the method argument list.

Let's create a specification where we use this feature. In the following sample we use a mock for the AgeService used in the class under test. The method allowedMaxTime() is invoked by the class under test and basically should return the maximum hour of the day a show can be broadcasted. In our specification we use the name of the show to return different values during the test.

package com.mrhaki.spock

@Grab('org.spockframework:spock-core:0.7-groovy-2.0')
import spock.lang.*

class SampleSpec extends Specification {

    final ClassUnderTest classUnderTest = new ClassUnderTest()

    @Unroll
    def "show #name with start time 21h is #expected to show"() {
        setup:
        final AgeService ageService = Mock()
        classUnderTest.ageService = ageService

        when:
        final boolean allowed = classUnderTest.listing(new Show(name: name, startTime: 21)) 

        then:
        1 * ageService.allowedMaxTime(_ as Show) >> { Show show ->
            show.name.toLowerCase().contains('kids') ? 10 : 23
        }
        // Alternative syntax with a non-typed closure argument:
        //1 * ageService.allowedMaxTime(_ as Show) >> { arguments ->
        //    arguments[0].name.toLowerCase().contains('kids') ? 10 : 23
        //}

        allowed == expected

        where:
        name            || expected
        'Kids rules'    || false
        'Sports united' || true
    }

}

/* Supporting classes and interface */

class ClassUnderTest {

    AgeService ageService

    boolean listing(final Show show) {
        final int hour = ageService.allowedMaxTime(show)
        show.startTime <= hour
    }
}

interface AgeService {
    int allowedMaxTime(Show show)
}

@groovy.transform.Canonical
class Show {
    String name
    int startTime
}

Code written with Spock 0.7-groovy-2.0.

Original post written on September 24, 2013

Writing Assertions for Arguments Mock Methods

My colleague Arthur Arts has written a blog post Tasty Test Tip: Using ArgumentCaptor for generic collections with Mockito. This inspired me to do the same in Spock. With the ArgumentCaptor in Mockito the parameters of a method call to a mock are captured and can be verified with assertions. In Spock we can also get a hold on the arguments that are passed to method call of a mock and we can write assertions to check the parameters for certain conditions.

When we create a mock in Spock and invoke a method on the mock the arguments are matched using the equals() implementation of the argument type. If they are not equal Spock will tell us by showing a message that there are too few invocations of the method call. Let's show this with an example. First we create some classes we want to test:

package com.mrhaki.spock

public class ClassUnderTest {

    private final Greeting greeting

    ClassUnderTest(final Greeting greeting) {
        this.greeting = greeting
    }

    String greeting(final List<Person> people) {
        greeting.sayHello(people)
    }
}
package com.mrhaki.spock

interface Greeting {
    String sayHello(final List<Person> people)
}
package com.mrhaki.spock

@groovy.transform.Canonical
class Person {
    String name
}    

Now we can write a Spock specification to test ClassUnderTest. We will now use the default matching of arguments of a mock provided by Spock.

package com.mrhaki.spock

import spock.lang.Specification

class SampleSpecification extends Specification {

    final ClassUnderTest classUnderTest = new ClassUnderTest()

    def "check sayHello is invoked with people in greeting method"() {
        given:
        final Greeting greeting = Mock()
        classUnderTest.greeting = greeting

        and:
        final List<Person> people = ['mrhakis', 'hubert'].collect { new Person(name: it) }

        when:
        final String greetingResult = classUnderTest.greeting(people)

        then:
        1 * greeting.sayHello([new Person(name: 'mrhaki'), new Person(name: 'hubert')])
    }

}

When we execute the specification we get a failure with the message that there are too few invocations:

...
Too few invocations for:

1 * greeting.sayHello([new Person(name: 'mrhaki'), new Person(name: 'hubert')])   (0 invocations)

Unmatched invocations (ordered by similarity):

1 * greeting.sayHello([com.jdriven.spock.Person(mrhakis), com.jdriven.spock.Person(hubert)])
...

To capture the arguments we have to use a different syntax for the method invocation on the mock. This time we define the method can be invoked with any number of arguments ((*_)) and then use a closure to capture the arguments. The arguments are passed to the closure as a list. We can then get the argument we want and write an assert statement.

package com.mrhaki.spock

import spock.lang.Specification

class SampleSpecification extends Specification {

    final ClassUnderTest classUnderTest = new ClassUnderTest()

    def "check sayHello is invoked with people in greeting method"() {
        given:
        final Greeting greeting = Mock()
        classUnderTest.greeting = greeting

        and:
        final List<Person> people = ['mrhakis', 'hubert'].collect { new Person(name: it) }

        when:
        final String greetingResult = classUnderTest.greeting(people)

        then:
        1 * greeting.sayHello(*_) >> { arguments ->
            final List<Person> argumentPeople = arguments[0]
            assert argumentPeople == [new Person(name: 'mrhaki'), new Person(name: 'hubert')]
        }
    }

}

We run the specification again and it will fail again (of course), but this time we get an assertion message:

...
Condition not satisfied:

argumentPeople == [new Person(name: 'mrhaki'), new Person(name: 'hubert')]
|              |   |                           |
|              |   |                           com.jdriven.spock.Person(hubert)
|              |   com.jdriven.spock.Person(mrhaki)
|              false
[com.jdriven.spock.Person(mrhakis), com.jdriven.spock.Person(hubert)]

    at com.jdriven.spock.SampleSpecification.check sayHello is invoked with people in greeting method_\
closure2(SampleSpecification.groovy:25)
...

Code written with Spock 0.7-groovy-2.0

Original post written on May 17, 2013

Use Stub or Mock For Spring Component Using @SpringBean

When we write tests or specifications using Spock for our Spring Boot application, we might want to replace some Spring components with a stub or mock version. With the stub or mock version we can write expected outcomes and behaviour in our specifications. Since Spock 1.2 and the Spock Spring extension we can use the @SpringBean annotation to replace a Spring component with a stub or mock version. (This is quite similar as the @MockBean for Mockito mocks that is supported by Spring Boot). We only have to declare a variable in our specification of the type of the Spring component we want to replace. We directly use the Stub() or Mock() methods to create the stub or mock version when we define the variable. From now on we can describe expected output values or behaviour just like any Spock stub or mock implementation.

To use the @SpringBean annotation we must add a dependency on spock-spring module to our build system. For example if we use Gradle we use the following configuration:

...
dependencies {
    ...
    testImplementation("org.spockframework:spock-spring:1.3-groovy-2.5")
    ...
}
...

Let's write a very simple Spring Boot application and use the @SpringBean annotation to create a stubbed component. First we write a simple interface with a method that accepts an argument of type String and return a new String value:

package mrhaki.spock;

public interface MessageComponent {
    String hello(final String name);
}

Next we use this interface in a Spring REST controller where we use constructor dependency injection to inject the correct implementation of the MessageComponent interface into the controller:

package mrhaki.spock;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageController {

    private final MessageComponent messageComponent;

    public MessageController(final MessageComponent messageComponent) {
        this.messageComponent = messageComponent;
    }

    @GetMapping(path = "/message", produces = MediaType.TEXT_PLAIN_VALUE)
    public String message(@RequestParam final String name) {
        return messageComponent.hello(name);
    }

}

To test the controller we write a new Spock specification. We use Spring's MockMvc support to test our controller, but the most important part in the specification is the declaration of the variable messageComponent with the annotation @SpringBean. Inside the method where we invoke /message?name=mrhaki we use the stub to declare our expected output:

package mrhaki.spock

import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.test.web.servlet.MockMvc
import spock.lang.Specification

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get

@WebMvcTest(MessageController)
class MessageControllerSpec extends Specification {

    @Autowired
    private MockMvc mockMvc

    /**
     * Instead of the real MessageComponent implementation
     * in the application context we want to use our own
     * Spock Stub implementation to have control over the
     * output of the message method.
     */
    @SpringBean
    private MessageComponent messageComponent = Stub()

    void "GET /message?name=mrhaki should return result of MessageComponent using mrhaki as argument"(\
) {
        given: 'Stub returns value if invoked with argument "mrhaki"'
        messageComponent.hello("mrhaki") >> "Hi mrhaki"

        when: 'Get response for /message?name=mrhaki'
        final response = mockMvc.perform(get("/message").param("name", "mrhaki"))
                                .andReturn()
                                .getResponse()

        then:
        response.contentAsString == "Hi mrhaki"
    }
}

Written with Spock 1.3-groovy-2.5 and Spring Boot 2.1.8.RELEASE.

Original post written on September 10, 2019