我正在开发一个Spring服务,它包含一个Camel处理器类,如下所示:
public class MyProc implements Processor {
@Autowired
private LogService logService;
public void process(Exchange e) {
// exchange object processing
logService.update(e)
}
}
我有以下的史波克测试:
class MyProcTest extends Specification {
@Shared def logService = Mock(LogService)
@Shared def proc = new MyProc()
def ctx = new DefaultCamelContext()
def exch = new DefaultExchange(ctx)
void setupSpec() {
proc.logService = logService
}
def "log is updated when valid exchange is processed"() {
given:
exch.getIn().setBody(//xml string set on body)
when:
proc.process(exch)
then:
1 * logService.update(_)
}
}
当我运行它时,我会得到一个失败,对1* logService.update(_) (0调用)的调用太少。我试着调试代码,在MyProc中,语句被击中,当突出显示logService对象时(在Eclipse中)状态是‘LogService类型的mock,名为$spock_sharedField_logService',所以看起来模拟已经成功地注入到MyProc实例中。
我对Spock和Groovy很陌生,所以我可能遗漏了一些东西,但测试不应该通过吗?在运行测试时,将调用mocks方法,因此我不明白为什么测试报告根本没有调用mocks方法。我是否在MyProc实例上初始化模拟/设置模拟/不正确地设置交互?是否有我忽略的Groovy特性或警告?据我所知,Spock模拟在调用时将从方法返回一个默认值,这很好,我只想检查这个特定的方法是否已作为proc.process的一部分被调用,并具有一个有效的exchange对象。
发布于 2016-12-16 16:17:55
一个简单的答案是不要将@Shared用于模拟/存根/间谍。
@Shared def proc = new MyProcessor()
def test() {
given:
def log = Mock(LogService)
proc.logService = log
when:
proc.process(new Object())
then:
1 * log.update(_)
}
现在解释一下:当您运行您的spec Spock时,它会为每个测试创建一个规范实例,另外,它还会创建一个共享规范实例来跟踪共享字段。
查看org.spockframework.runtime.BaseSpecRunner,您将看到两个字段:
protected Specification sharedInstance;
protected Specification currentInstance;
此外,还有两个规范上下文:共享和当前。上下文保存实例、模拟上下文和模拟控制器。问题来了。当您将模拟声明为shared时,它将绑定到共享模拟控制器,但是当您将declair交互(‘然后:’块)添加到当前模拟控制器中时,Spock将这些交互添加到当前的模拟控制器中。因此,当调用模拟方法(例如,logService.update(e))时,史波克检查共享模拟控制器是否允许这种交互,因为您将模拟声明为shared,但在那里找不到任何东西,因为您将交互放在当前控制器中。
不要使用模拟/存根/间谍作为@共享字段。
https://stackoverflow.com/questions/41148561
复制相似问题