当前位置:   article > 正文

使用spock进行单元测试_spock单元测试

spock单元测试

从简单到困难,一步步教你用Spock写单元测试

1. 安装Spock

首先,你需要在你的项目中安装Spock。如果你使用的是Gradle,可以在build.gradle文件中添加以下依赖:

testImplementation 'org.spockframework:spock-core:2.0-M3-groovy-3.0'
  • 1

如果你使用的是Maven,可以在pom.xml文件中添加以下依赖:

<dependency>
    <groupId>org.spockframework</groupId>
    <artifactId>spock-core</artifactId>
    <version>2.0-M3-groovy-3.0</version>
    <scope>test</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2. 编写第一个测试

接下来,让我们编写一个简单的测试。假设我们有一个名为Calculator的类,其中有一个add方法,用于将两个数字相加。我们想要测试这个方法是否正确地计算了结果。

我们可以创建一个名为CalculatorSpec的类,其中包含以下代码:

import spock.lang.Specification

class CalculatorSpec extends Specification {
    def "test add method"() {
        given:
        Calculator calculator = new Calculator()

        when:
        def result = calculator.add(2, 3)

        then:
        result == 5
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这个测试中,我们使用了Spock的BDD(行为驱动开发)语法。我们使用given块初始化测试数据,when块执行我们要测试的方法,then块验证结果是否符合预期。

3. 使用数据驱动测试

接下来,让我们使用数据驱动测试来测试add方法。我们可以使用Spock的where块来定义测试数据,如下所示:

import spock.lang.Specification

class CalculatorSpec extends Specification {
    def "test add method"() {
        given:
        Calculator calculator = new Calculator()

        when:
        def result = calculator.add(a, b)

        then:
        result == expected

        where:
        a | b | expected
        2 | 3 | 5
        5 | 7 | 12
        10 | 0 | 10
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

在这个测试中,我们使用了where块来定义测试数据。我们定义了三组输入数据和预期输出结果,Spock会自动运行这些数据并验证结果是否符合预期。

4. 使用Mock对象测试

接下来,让我们使用Mock对象来测试Calculator类。假设Calculator类依赖于一个名为MathService的服务,我们想要测试Calculator类是否正确地使用了这个服务。

我们可以使用Spock的Mock对象来模拟MathService服务,如下所示:

import spock.lang.Specification
import spock.lang.Mock

class CalculatorSpec extends Specification {
    @Mock
    MathService mathService

    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(2, 3)

        then:
        result == 5
        1 * mathService.add(2, 3) >> 5
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在这个测试中,我们使用了Spock的@Mock注解来创建一个MathService的Mock对象。我们还使用了1 * mathService.add(2, 3) >> 5语法来指定当mathService.add(2, 3)方法被调用时返回5。

5. 使用交互测试

最后,让我们使用交互测试来测试Calculator类是否正确地调用了MathService服务。我们可以使用Spock的@Unroll注解来展开测试结果,如下所示:

import spock.lang.Specification
import spock.lang.Mock
import spock.lang.Unroll

class CalculatorSpec extends Specification {
    @Mock
    MathService mathService

    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(a, b)

        then:
        result == expected
        1 * mathService.add(a, b) >> expected

        @Unroll
        "a=#a, b=#b, expected=#expected":
        [a: 2, b: 3, expected: 5],
        [a: 5, b: 7, expected: 12],
        [a: 10, b: 0, expected: 10]
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在这个测试中,我们使用了@Unroll注解来展开测试结果,这样我们就可以看到每组测试数据的结果。我们还使用了1 * mathService.add(a, b) >> expected语法来指定当mathService.add(a, b)方法被调用时返回expected值。

6. 使用@Shared注解

在Spock中,每个测试方法都会创建一个新的测试实例。如果测试中有多个测试方法,每个方法都会创建一个新的实例,这可能会导致测试运行速度变慢。为了避免这种情况,我们可以使用@Shared注解来创建一个实例,该实例在所有测试方法之间共享。

例如,我们可以在CalculatorSpec类中使用@Shared注解来创建一个共享的Calculator对象,如下所示:

import spock.lang.Specification
import spock.lang.Mock
import spock.lang.Unroll

class CalculatorSpec extends Specification {
    @Shared
    Calculator calculator = new Calculator()

    @Mock
    MathService mathService

    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(a, b)

        then:
        result == expected
        1 * mathService.add(a, b) >> expected

        @Unroll
        "a=#a, b=#b, expected=#expected":
        [a: 2, b: 3, expected: 5],
        [a: 5, b: 7, expected: 12],
        [a: 10, b: 0, expected: 10]
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

在这个测试中,我们使用了@Shared注解来创建一个共享的Calculator对象,这样在所有测试方法之间都可以使用相同的对象。

7. 使用@Ignore注解

有时候,我们可能需要暂时忽略某个测试方法,例如当我们正在解决某个bug时。我们可以使用@Ignore注解来暂时忽略某个测试方法,如下所示:

import spock.lang.Specification
import spock.lang.Mock
import spock.lang.Unroll

class CalculatorSpec extends Specification {
    @Shared
    Calculator calculator = new Calculator()

    @Mock
    MathService mathService

    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(a, b)

        then:
        result == expected
        1 * mathService.add(a, b) >> expected

        @Unroll
        "a=#a, b=#b, expected=#expected":
        [a: 2, b: 3, expected: 5],
        [a: 5, b: 7, expected: 12],
        [a: 10, b: 0, expected: 10]
    }

    @Ignore
    def "test subtract method"() {
        given:
        Calculator calculator = new Calculator()

        when:
        def result = calculator.subtract(a, b)

        then:
        result == expected

        where:
        a | b | expected
        5 | 3 | 2
        10 | 5 | 5
        15 | 7 | 8
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

在这个测试中,我们使用了@Ignore注解来暂时忽略test subtract method测试方法。

8. 使用@Timeout注解

有时候,我们可能需要限制测试方法的执行时间,以避免测试运行时间过长。我们可以使用@Timeout注解来限制测试方法的执行时间,如下所示:

import spock.lang.Specification
import spock.lang.Mock
import spock.lang.Unroll

class CalculatorSpec extends Specification {
    @Shared
    Calculator calculator = new Calculator()

    @Mock
    MathService mathService

    @Timeout(1000)
    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(a, b)

        then:
        result == expected
        1 * mathService.add(a, b) >> expected

        @Unroll
        "a=#a, b=#b, expected=#expected":
        [a: 2, b: 3, expected: 5],
        [a: 5, b: 7, expected: 12],
        [a: 10, b: 0, expected: 10]
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

在这个测试中,我们使用了@Timeout(1000)注解来限制test add method测试方法的执行时间为1秒。如果测试方法超过了指定的时间,测试将会失败。

9. 使用@Stepwise注解

有时候,我们可能需要按顺序执行测试方法,以确保测试的正确性。我们可以使用@Stepwise注解来按顺序执行测试方法,如下所示:

import spock.lang.Specification
import spock.lang.Mock
import spock.lang.Unroll

@Stepwise
class CalculatorSpec extends Specification {
    @Shared
    Calculator calculator = new Calculator()

    @Mock
    MathService mathService

    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(a, b)

        then:
        result == expected
        1 * mathService.add(a, b) >> expected

        @Unroll
        "a=#a, b=#b, expected=#expected":
        [a: 2, b: 3, expected: 5],
        [a: 5, b: 7, expected: 12],
        [a: 10, b: 0, expected: 10]
    }

    def "test subtract method"() {
        given:
        Calculator calculator = new Calculator()

        when:
        def result = calculator.subtract(a, b)

        then:
        result == expected

        where:
        a | b | expected
        5 | 3 | 2
        10 | 5 | 5
        15 | 7 | 8
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

在这个测试中,我们使用了@Stepwise注解来按顺序执行测试方法。首先执行test add method测试方法,然后执行test subtract method测试方法。如果test add method测试方法失败,test subtract method测试方法将不会执行。

10. 使用@IgnoreRest注解

有时候,我们可能需要在测试方法失败后停止执行后续测试方法,以避免测试结果受到之前测试方法的影响。我们可以使用@IgnoreRest注解来在测试方法失败后停止执行后续测试方法,如下所示:

import spock.lang.Specification
import spock.lang.Mock
import spock.lang.Unroll

class CalculatorSpec extends Specification {
    @Shared
    Calculator calculator = new Calculator()

    @Mock
    MathService mathService

    def "test add method"() {
        given:
        Calculator calculator = new Calculator(mathService)

        when:
        def result = calculator.add(a, b)

        then:
        result == expected
        1 * mathService.add(a, b) >> expected

        @Unroll
        "a=#a, b=#b, expected=#expected":
        [a: 2, b: 3, expected: 5],
        [a: 5, b: 7, expected: 12],
        [a: 10, b: 0, expected: 10]
    }

    @IgnoreRest
    def "test subtract method"() {
        given:
        Calculator calculator = new Calculator()

        when:
        def result = calculator.subtract(a, b)

        then:
        result == expected

        where:
        a | b | expected
        5 | 3 | 3
        10 | 5 | 5
        15 | 7 | 8
    }

    def "test divide method"() {
        given:
        Calculator calculator = new Calculator()

        when:
        def result = calculator.divide(a, b)

        then:
        result == expected

        where:
        a | b | expected
        10 | 2 | 5
        20 | 4 | 5
        30 | 5 | 6
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

在这个测试中,我们使用了@IgnoreRest注解来在test subtract method测试方法失败后停止执行后续测试方法。如果test subtract method测试方法失败,test divide method测试方法将不会执行。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/760038
推荐阅读
相关标签
  

闽ICP备14008679号