Java 模拟groovy新文件.eachFile()

Java 模拟groovy新文件.eachFile(),java,groovy,Java,Groovy,我在模拟file.eachFile(){}时遇到问题 我试图模拟从file.eachFile{}返回的文件-我不想实际测试驱动器上真实目录的内容 我不知道如何使用Spock实现这一点(据我所知,它更多地用于模拟验证) 因此,我决定使用“本机”Groovy模拟功能和MOP功能。 不走运 例如(为了将对象传递给测试函数,我必须删除文件类型): 或者(使用元类): I每个文件方法的定义如下: public static void eachFile(final File self, final Clos

我在模拟file.eachFile(){}时遇到问题

我试图模拟从file.eachFile{}返回的文件-我不想实际测试驱动器上真实目录的内容

我不知道如何使用Spock实现这一点(据我所知,它更多地用于模拟验证)

因此,我决定使用“本机”Groovy模拟功能和MOP功能。 不走运

例如(为了将对象传递给测试函数,我必须删除文件类型):

或者(使用元类):

I每个文件方法的定义如下:

public static void eachFile(final File self, final Closure closure) throws FileNotFoundException, IllegalArgumentException {
        eachFile(self, FileType.ANY, closure);
    }
我已经有点模糊,从所有的编码尝试来模拟这:)

我设法找到了这个方法(没有运行时异常),但实际上无法看到预先定义的文件列表的注入

测试方法为(为简单起见):

在Java中,Mockito会在一分钟内完成这项工作,但我在某处读到关于与Groovy集成的一些问题。模拟类时会出现问题,因为Groovy会调用元类

我看到了这个


蒂姆·耶茨写道:

def mock = new MockFor(File)
mock.demand.eachFile {
  [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each { (it) }
}

mock.use {
  new File('.').eachFile {file ->
    println "$file"
  }
def mock = new MockFor(File)
mock.demand.eachFile {
  [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each { (it) }
}

mock.use {
  new File('.').eachFile {file ->
    println "$file"
  }
脚本可以工作,但是在测试中使用它时有一个缺点

正如我提到的,我使用的是Spock,file变量通过一个方法传递。 因此,以您编写的方式使用它会导致:

groovy.lang.MissingMethodException: No signature of method: groovy.mock.interceptor.MockFor.eachFile() is applicable for argument types: ... 
我猜这是因为代码中没有直接使用File.eachFile()(它没有将mock传递给方法,它希望在“use”块中实例化mock)

测试中的代码如下所示:

when:
    mock.use {
      folderValidator.validate(mock)
    }

then:
    folderValidator.listMissingFiles.size == 3
proxyInstance()的问题是,它应该将模拟传递到方法中,如示例所示:

when:
    folderValidator.validate(mockProxy)

then:
    folderValidator.listMissingFiles.size == 3
当mock被传递时,groovy无法实例化该类,因为它不知道使用哪个构造函数

org.codehaus.groovy.runtime.metaclass.MethodSelectionException: Could not find which method <init>() to invoke from this list:

  private java.io.File#<init>(java.lang.String, int)
  private java.io.File#<init>(java.lang.String, java.io.File)
  public  java.io.File#<init>(java.lang.String)
  public  java.io.File#<init>(java.net.URI)
  public  java.io.File#<init>(java.io.File, java.lang.String)
  public  java.io.File#<init>(java.lang.String, java.lang.String)
org.codehaus.groovy.runtime.metaclass.MethodSelectionException:无法从该列表中找到要调用的方法():
私有java.io.File#(java.lang.String,int)
私有java.io.File#(java.lang.String,java.io.File)
公共java.io.File#(java.lang.String)
公共java.io.File#(java.net.URI)
公共java.io.File#(java.io.File,java.lang.String)
公共java.io.File#(java.lang.String,java.lang.String)
理论上,它可以工作,但在这个例子中它失败了,也许我编错了。我两周前就开始使用Groovy了,所以我还是习惯了。
谢谢你蒂姆·耶茨写道:

def mock = new MockFor(File)
mock.demand.eachFile {
  [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each { (it) }
}

mock.use {
  new File('.').eachFile {file ->
    println "$file"
  }
def mock = new MockFor(File)
mock.demand.eachFile {
  [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each { (it) }
}

mock.use {
  new File('.').eachFile {file ->
    println "$file"
  }
他是对的。正如我所说,我使用Groovy的时间没有那么长(斯波克也没有)

“我猜这是因为代码中没有直接使用File.eachFile()(它没有将模拟传递给方法,它希望模拟在“use”块中实例化)?”

测试中的代码如下所示:

when:

        mock.use {
          folderValidator.validate(new File("."))
        }

then:
        folderValidator.listMissingFiles.size == 3
解决方案是简单地在use块内实例化模拟类。我认为mock是实例化的,并将以Mockito的工作方式在方法中传递

莫基托:

File pathScripts;
pathScripts = mock(File.class);
when(pathScripts.list()).thenReturn(listFiles);

someObject.someTestingMethod(pathScripts)
proxyInstance的方法是模拟类,但是使用正确的构造函数参数

def mock = new MockFor(File)
mock.demand.eachFile {func ->
  [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each { func(it) }
}

def mockProxy = mock.proxyInstance(".")

mockProxy.eachFile {file ->
  println "$file"
}
最大的错误是我的模拟方法中缺少闭包:

mockFile.demand.eachFile { **??** [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each {**?**(it)}} 

所以,谢谢你们,tim_yates

这是有效的,因为文件有一个单参数构造函数。那么多参数构造函数呢?应该工作相同吗?我真的记不清所有的细节,但我认为它应该很好用。如果在模拟接口时遇到问题,我建议您将所需的模拟隐藏在接口后面。FileFactory与文件创建(…所需参数…)方法的接口。
mockFile.demand.eachFile { **??** [new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each {**?**(it)}}