非静态方法的GroovyMock是否具有指定的行为?

非静态方法的GroovyMock是否具有指定的行为?,groovy,mocking,spock,non-static,Groovy,Mocking,Spock,Non Static,我把这个放在我的斯波克测试中: GroovyMock( File, global: true) File.createNewFile() >> null 。。。我意识到这是非正统的/愚蠢的/奇怪的:createNewFile是一种非静态方法 涉及的代码如下所示: if( indexInfoFile.createNewFile() ) { 。。。根据我的经验,像这样模拟createNewFile总是返回false,即使您尝试在模拟中放置块: GroovyMock( File, gl

我把这个放在我的斯波克测试中:

GroovyMock( File, global: true)
File.createNewFile() >> null
。。。我意识到这是非正统的/愚蠢的/奇怪的:
createNewFile
是一种非静态方法

涉及的代码如下所示:

if( indexInfoFile.createNewFile() ) {
。。。根据我的经验,像这样模拟
createNewFile
总是返回
false
,即使您尝试在模拟中放置块:

GroovyMock( File, global: true)
File.createNewFile() >> {
    log.info( 'Hello mum!')
}
。。。日志消息未打印,但
createNewFile
再次返回
false

这实际上是我想要的(即模拟
false
createNewFile
返回)

这是故意的、有记录的行为吗

PS告诫:根据我今天的经验/实验,毫无疑问,此模拟方法确实会在任何
文件
实例上替换此方法调用的所有实例。然而,它似乎也有一些令人担忧的副作用:例如,我在
给定的
块中创建的一个目录,在2
GroovyMock
行之后被发现存在,当我去时仍然在
给定的
块中

myDirPath.toFile().exists()
。。。我假设这是因为
toFile
涉及调用
createNewFile

因为Groovy mock在与Groovy类一起使用时只有额外的“魔力”,但我假设您正在尝试模拟
java.io.File
,这是一个java JRE类。因此,Groovy模拟的行为将类似于普通的Spock模拟。因此,我不知道您首先为什么要使用Groovy mock——可能是因为您想使用
global:true
特性,以避免重构应用程序类中的可测试性

由于您没有向我们展示一个,我无法知道是否可以将
indexInfoFile
注入到您测试的类/方法中,或者它是否是在方法内部创建的依赖项。在后一种情况下,您需要重构,就这么简单。依赖项应该是可注入的,句号为

至于您的代码片段,它们有一些问题:

  • 方法
    File.createNewFile()
    返回
    boolean
    ,因此将其存根为返回
    null
    没有任何意义
  • 创建模拟时,所有方法将自动返回
    false
    null
    0
    ,具体取决于它们的返回类型。因此,如果您希望
    createNewFile()
    返回
    false
    ,则无需首先为
    createNewFile()存根结果,因为它已经返回了
  • 您不能通过尝试像静态方法一样重写实例方法来存根实例方法。这毫无意义。请先学习Spock语法
现在,假设您正在测试的类看起来是这样的(已经准备好或重构,以便通过方法参数、构造函数参数或setter进行依赖注入)

package de.scrum_master.stackoverflow.q59842227;
导入java.io.File;
导入java.io.IOException;
导入java.util.Random;
公共类FileCreator{
私有静态最终随机=新随机();
公共布尔createIndexInfoFile(File indexInfoFile)引发IOException{
if(indexInfoFile.createNewFile()){
System.out.println(“文件\”+indexInfoFile+“\”已创建”);
返回true;
}
System.out.println(“文件\”+indexInfoFile+“\”未创建”);
返回false;
}
公共静态void main(字符串[]args)引发IOException{
新建FileCreator().createIndexInfoFile(
新文件(“\u abc\u”+RANDOM.nextInt(10000)+”.txt”)
);
}
}
。。。然后你可以像这样测试它:

if( indexInfoFile.createNewFile() ) {
package de.scrum\u master.stackoverflow.q59842227
导入spock.lang.Specification
类FileCreatorTest扩展了规范{
def“已创建索引信息文件”(){
鉴于:
File=Mock(){
createNewFile()>>true
}
期望:
新建FileCreator().createIndexInfoFile(文件)
}
def“未创建索引信息文件”(){
鉴于:
File=Mock()
期望:
!new FileCreator().createIndexInfoFile(文件)
}
}
看到了吗?不需要全局或Groovy模拟,普通模拟就可以了。但是您需要使代码可测试,而不是使用花哨的技巧。

正如Groovy mock在与Groovy类一起使用时只有额外的“魔力”,但我假设您正在尝试模拟java JRE类的
java.io.File
。因此,Groovy模拟的行为将类似于普通的Spock模拟。因此,我不知道您首先为什么要使用Groovy mock——可能是因为您想使用
global:true
特性,以避免重构应用程序类中的可测试性

由于您没有向我们展示一个,我无法知道是否可以将
indexInfoFile
注入到您测试的类/方法中,或者它是否是在方法内部创建的依赖项。在后一种情况下,您需要重构,就这么简单。依赖项应该是可注入的,句号为

至于您的代码片段,它们有一些问题:

  • 方法
    File.createNewFile()
    返回
    boolean
    ,因此将其存根为返回
    null
    没有任何意义
  • 创建模拟时,所有方法将自动返回
    false
    null
    0
    ,具体取决于它们的返回类型。因此,如果您希望
    createNewFile()
    返回
    false
    ,则无需首先为
    createNewFile()存根结果,因为它已经返回了
  • 您不能通过尝试像静态方法一样重写实例方法来存根实例方法。这毫无意义。请先学习Spock语法
现在,假设您正在测试的类看起来是这样的(已经准备好或重构,以便通过方法参数、构造函数参数或setter进行依赖注入)

package de.scrum_master.stackoverflow.q59842227;
导入java.io.File;
导入java.io.IOException;