就像你说的:
这种方法不起作用,因为 canTransitionTo() 不需要数组列表
因此,您需要确保遍历列表。多亏了 Groovy 的优点,您有了方便的方法。 next.every { current.canTransitionTo(it) }呢?
package de.scrum_master.stackoverflow.q68674245
import spock.lang.Specification
import spock.lang.Unroll
import static de.scrum_master.stackoverflow.q68674245.StateMachineTest.StateMachine.*
class StateMachineTest extends Specification {
@Unroll("#current state can successfully transit to #next")
def "Validate the successful transition of the state machine"() {
expect:
next.every { current.canTransitionTo(it) }
where:
current | next
STATE_A | STATE_B
STATE_A | STATE_C
STATE_A | [STATE_B, STATE_C]
START | [STATE_A, STATE_B, STATE_C]
STATE_C | [STATE_B, START] // fails, because START is a forbidden target state
}
static enum StateMachine {
START, STATE_A, STATE_B, STATE_C
boolean canTransitionTo(StateMachine stateMachine) {
println "transition $this -> $stateMachine"
return stateMachine != START
}
}
}
您甚至可以更进一步,在转换的两端允许迭代:
package de.scrum_master.stackoverflow.q68674245
import spock.lang.Specification
import spock.lang.Unroll
import static de.scrum_master.stackoverflow.q68674245.StateMachineTest.StateMachine.*
class StateMachineTest extends Specification {
@Unroll("#current can transit to #next")
def "Validate successful transition of the state machine"() {
expect:
current.every { from -> next.every { to -> from.canTransitionTo(to) } }
where:
current | next
[START, STATE_A, STATE_B, STATE_C] | [STATE_A, STATE_B, STATE_C]
}
@Unroll("#current must not transit to #next")
def "Validate failed state machine transition"() {
expect:
current.every { from -> next.every { to -> !from.canTransitionTo(to) } }
where:
current | next
[START, STATE_A, STATE_B, STATE_C] | START
}
static enum StateMachine {
START, STATE_A, STATE_B, STATE_C
boolean canTransitionTo(StateMachine stateMachine) {
println "transition $this -> $stateMachine"
return stateMachine != START
}
}
}
P.S.:在上述情况下,如果数据表仅包含单行,则实际上不需要 where 块。但我假设您的状态机比我的示例复杂一些,您需要指定更多差异化的情况。