Master Spock & Mockito: Seamless Unit Testing with Gradle

This article introduces the Groovy‑based Spock framework and the Mockito mocking library, shows how to configure them together in Gradle, and provides detailed Groovy demo code illustrating various mocking, spying, verification, and exception‑handling techniques for robust Java unit testing.

FunTester
FunTester
FunTester
Master Spock & Mockito: Seamless Unit Testing with Gradle

Spock is a Groovy‑based unit‑testing framework built on JUnit, currently at version 2.0, which requires recent Groovy and Java versions.

Mockito is a mocking framework that enables concise, readable unit tests and is essential for test‑driven development when dependencies need to be simulated.

To use both frameworks together, add the following Gradle dependencies:

testCompile 'org.mockito:mockito-core:2.7.22'
testCompile group: 'org.spockframework', name: 'spock-core', version: '1.3-groovy-2.5'
testCompile group: 'org.springframework', name: 'spring-test', version: '5.1.9.RELEASE'
testCompile group: 'org.hamcrest', name: 'hamcrest-library', version: '1.3'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0'
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.2'

The article provides a comprehensive Spock test class written in Groovy that demonstrates:

Shared resources and logger setup.

Mocking a List and configuring return values with Mockito.

Verifying method call counts using Mockito verification modes.

Mocking iterators, spying on real objects, and handling exceptions.

Using doAnswer and returnsFirstArg to customize mock behavior.

Differences between spy and mock regarding default method execution.

package com.FunTester.mockito.practise

import org.apache.http.client.methods.HttpRequestBase
import org.slf4j.Logger
import spock.lang.Shared
import spock.lang.Specification
import static com.fun.config.Constant.SPACE_1
import static com.fun.frame.SourceCode.getLogger
import static org.mockito.AdditionalAnswers.returnsFirstArg
import static org.mockito.Matchers.anyInt
import static org.mockito.Mockito.*

class Demo extends Specification {

    @Shared
    Logger logger = getLogger(this.getClass().getName())

    @Shared
    List listsss = mock(List)

    @Shared
    HttpRequestBase httpRequestBase = mock(HttpRequestBase.class)

    def setup() {
        logger.info("测试方法开始了")
    }

    def cleanup() {
        logger.info("测试方法结束了")
    }

    def setupSpec() {
        logger.info("测试类[${getClass().getName()}]开始了")
    }

    def cleanupSpec() {
        logger.info("测试类[${getClass().getName()}]结束了")
    }

    def "这是一个普通的demo"() {
        given: "创建一个存根list,添加一些元素"
        List mockedList = mock(List.class);
        mockedList.add("one");
        mockedList.add("two");
        mockedList.add("three times");
        mockedList.add("three times");
        mockedList.add("three times");
        when(mockedList.size()).thenReturn(5);
        mockedList.add("3")
        mockedList.add("3")
        mockedList.add("3")
        mockedList.add("3")

        expect: "验证属性以及方法调用次数"
        5 == mockedList.size()
        false == verify(mockedList, atLeastOnce()).add("one")
        false == verify(mockedList, times(3)).add("three times")
        false == verify(mockedList, atMost(4)).add("3")
        false == verify(mockedList, never()).add("30")
    }

    def "这是一个测试的mockito模拟方法返回"() {
        given: "虚拟一个迭代器对象"
        def iterator = mock(Iterator.class)
        when(iterator.next()).thenReturn("hello").thenReturn("world")

        expect: "测试迭代器元素拼接"
        "hello world" == iterator.next() + SPACE_1 + iterator.next()
    }

    def "这是一个测试,用来在对象初始化之后mock对象的"() {
        given: "创建对象后再Mockito"
        def iterator = new ArrayList()
        iterator.add("323")
        def list = spy(iterator)
        doReturn("fun").when(list).get(3)
        doReturn(3).when(list).get(0)

        expect:
        list.contains("323")
        "fun" == list.get(3)
        3 == list.get(0)
    }

    def "这是一个测试,抛出异常的测试用例"() {
        given: "创建测试对象"
        def object = mock(ArrayList.class)
        when(object.get(1)).thenThrow(new IndexOutOfBoundsException("我是测试"))
        def re = 0
        try {
            object.get(1)
        } catch (IndexOutOfBoundsException e) {
            re = 1
        }

        expect:
        re == 1
    }

    def "这是一个测试方法返回值的用例"() {
        given:
        def j = mock(DemoJ.class)
        doAnswer(returnsFirstArg()).when(j).ds(anyInt(), anyInt())

        expect:
        3 == j.ds(3, 32)
    }

    def "我是测试共享Mock对象的用例"() {
        given:
        when(listsss.get(anyInt())).thenReturn(3)

        expect:
        3 == listsss.get(3)
    }

    def "spy和mock区别"() {
        given:
        def list = [1,2,3,4]
        def integers = spy(list)
        when(integers.size()).thenReturn(9)

        expect:
        integers.size() == 9
        integers.get(0) == 1
    }
}

Testing confirmed that Mockito works smoothly within Spock, though some advanced syntax may be unavailable; in practice many projects combine both frameworks after evaluating their differences.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaGradleunit testingMockitoGroovySpock
FunTester
Written by

FunTester

10k followers, 1k articles | completely useless

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.