Spock - 如何检查 Spy 对象的方法调用计数?
Spock - How to check method invocation count on a Spy object?
我很难让这个 spock 测试起作用。
我有一个 Spring repo/DAO class 多次调用存储过程。我正在尝试编写一个单元测试来验证 SP 是否被调用 'x' 次(3 次调用 createSP() 方法)。
public class PlanConditionRepositoryImpl{
....
public void write() {
for (int i=0; i<3; i++) {
createSP(new ConditionGroup(), new Condition()).call();
}
}
protected StoredProcedure<Void> createSP(ConditionGroup planConditionGroup, Condition planCondition) {
return new StoredProcedure<Void>()
.jdbcTemplate(getJdbcTemplate())
.schemaName(SCHEMA_NAME);
}
}
但是下面的实现并没有这样做。如何实现调用计数检查?或者如何避免调用 createSP()
方法的实际实现。
def write(){
def repo = Spy(PlanConditionRepositoryImpl){
createSP(_, _) >> Spy(StoredProcedure){
call() >> {
//do nothing
}
}
}
when:
repo.write()
then:
3 * repo.createSP(_, _)
}
这就是我使用 hack 解决它的方法。但是有没有使用Spock的基于交互的测试而不引入额外变量的解决方案?
def "spec"() {
given:
def count = 0
def spy = Spy(PlanConditionRepositoryImpl){
createSP(_, _) >> {count++}
}
when:
spy.write()
then:
count == 3
}
你需要的是部分模拟,看看docs。然而,正如我所说,部分模拟基本上是不好的做法,可能表明设计不好:
(Think twice before using this feature. It might be better to change
the design of the code under specification.)
关于部分模拟:
// this is now the object under specification, not a collaborator
def persister = Spy(MessagePersister) {
// stub a call on the same object
isPersistable(_) >> true
}
when:
persister.receive("msg")
then:
// demand a call on the same object
1 * persister.persist("msg")
测试应该这样写:
@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
@Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def "spec"() {
given:
def mock = Mock(StoredProcedure)
def spy = Spy(PlanConditionRepositoryImpl)
when:
spy.write()
then:
3 * spy.createSP() >> mock
3 * mock.run()
}
}
class PlanConditionRepositoryImpl {
void write() {
for (int i = 0; i < 3; i++) {
createSP().run()
}
}
StoredProcedure createSP() {
new StoredProcedure()
}
}
class StoredProcedure {
def run() {}
}
我很难让这个 spock 测试起作用。
我有一个 Spring repo/DAO class 多次调用存储过程。我正在尝试编写一个单元测试来验证 SP 是否被调用 'x' 次(3 次调用 createSP() 方法)。
public class PlanConditionRepositoryImpl{
....
public void write() {
for (int i=0; i<3; i++) {
createSP(new ConditionGroup(), new Condition()).call();
}
}
protected StoredProcedure<Void> createSP(ConditionGroup planConditionGroup, Condition planCondition) {
return new StoredProcedure<Void>()
.jdbcTemplate(getJdbcTemplate())
.schemaName(SCHEMA_NAME);
}
}
但是下面的实现并没有这样做。如何实现调用计数检查?或者如何避免调用 createSP()
方法的实际实现。
def write(){
def repo = Spy(PlanConditionRepositoryImpl){
createSP(_, _) >> Spy(StoredProcedure){
call() >> {
//do nothing
}
}
}
when:
repo.write()
then:
3 * repo.createSP(_, _)
}
这就是我使用 hack 解决它的方法。但是有没有使用Spock的基于交互的测试而不引入额外变量的解决方案?
def "spec"() {
given:
def count = 0
def spy = Spy(PlanConditionRepositoryImpl){
createSP(_, _) >> {count++}
}
when:
spy.write()
then:
count == 3
}
你需要的是部分模拟,看看docs。然而,正如我所说,部分模拟基本上是不好的做法,可能表明设计不好:
(Think twice before using this feature. It might be better to change the design of the code under specification.)
关于部分模拟:
// this is now the object under specification, not a collaborator
def persister = Spy(MessagePersister) {
// stub a call on the same object
isPersistable(_) >> true
}
when:
persister.receive("msg")
then:
// demand a call on the same object
1 * persister.persist("msg")
测试应该这样写:
@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
@Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def "spec"() {
given:
def mock = Mock(StoredProcedure)
def spy = Spy(PlanConditionRepositoryImpl)
when:
spy.write()
then:
3 * spy.createSP() >> mock
3 * mock.run()
}
}
class PlanConditionRepositoryImpl {
void write() {
for (int i = 0; i < 3; i++) {
createSP().run()
}
}
StoredProcedure createSP() {
new StoredProcedure()
}
}
class StoredProcedure {
def run() {}
}