Spock Test Framework 入门
Spock 是使用 Groovy 进行单元测试,用于替代 JUnit 的单元测试框架
Groovy
Advantages
- Easy to learn
- Java: syntax and integration
- Optionally typed and dynamic
- Static typing and static compilation capabilities (静态类型)
Spock
- Grovvy based
- BDD structure (Behavior Driven Development)
- given-when-then
- Clear tests for Java code
测试类结构
import spock.lang.*
class MySpec extends Specification {
def setup () {
// ...
}
def "test context loads"() {
given:// alias: setup
when: // ...
then: // ...
expect: // ...
where: // ...
}
def cleanup() {
// ...
}
}
上述示例中, setup 函数为当前测试文件的初始配置 cleanup 函数在所有测试执行完成之后会被调用,用于清理单测所创建的资源。
given-when-then
def "team is using spock"() {
given: "xxxx"
'spock'in team.frameworks
when: "xxxx"
def feature = team.addNewFeature()
then: "xxxx"
! feature.tests.empty
feature.tests.every{
it.clear
}
}
when-then & expect
def "should calculate power of number 2"() {
when:
def x = Math.pow(2)
then:
x == 4
}
def "should calculate power of number 2"() {
expect:
Math.pow(2) == 4
}
expect-where
def "computing the maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a << [5, 3]
b << [1, 9]
c << [5, 9]
}
如下方式也是可以的
def "computing the maximum of two numbers"() {
expect:
Math.max(a, b) == c
where:
a | b | c
5 | 1 | 5
3 | 9 | 9
}
Test failure
def "should return 2 from first element of list"() {
given:
def list = []
when:
list.add(1)
then:
2 == list.get(0)
}
/*
Test Result:
Condition not satisfied:
2 == list.get(0)
| | |
| [1] 1
false
*/
thrown VS notThrown
thrown
// thrown
def "Cannot pop from empty stack"() {
when:
stack.pop()
then:
thrown(EmptyStackException)
stack.empty
}
notThrown
def "HashMapaccepts null key"() {
setup:
def map = newHashMap()
when:
map.put(null, "elem")
then:
notThrown(NullPointerException)
}
Mock
Mock 关注调用次数以及调用时的参数,_
表示不关心
ExtenalService service1 = Mock()
AnotherService service2 = Mock()
WhateverService service3 = Mock()
1 * service1.receive("hello")
0 * service2.receive("hello")
(1..3) * service3.receive("hello")
(1.._) * service1.receive("hello")
(_..3) * service2.receive("hello")
_ * service3.receive("hello")
1 * _.receive("hello")
1 * service1./r.*e/("hello")
1 * service2.receive(!"hello")
1 * service3.receive()
1 * service1.receive(_)
1 * service2.receive(*_)
1 * service3.receive(!null)
1 * service1.receive(_ as String)
1 * service2.receive({ it.size() > 3 })
Grouping Interactions with Same Target
Interactions sharing the same target can be grouped in a Specification.with
block. Similar to Declaring Interactions at Mock Creation Time, this makes it unnecessary to repeat the target constraint:
with(subscriber) {
1 * receive("hello")
1 * receive("goodbye")
}
Stubbing
使具体一个函数返回某值。如下有一个 Subscriber 接口
interface Subscriber {
String receive(String message)
}
使 receive
每次都返回 "ok"
subscriber.receive(_) >> "ok"
| | | |
| | | response generator
| | argument constraint
| method constraint
target constraint
或者根据不同的输入进行返回
subscriber.receive("message1") >> "ok"
subscriber.receive("message2") >> "fail"
了解更多
- https://spockframework.org/
- http://groovy-lang.org/