【问题标题】:Mocking groovy new File.eachFile()模拟 groovy new File.eachFile()
【发布时间】:2011-06-29 03:29:58
【问题描述】:

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

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

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

所以,我决定使用“原生”Groovy mock 功能MOP 功能。 没有运气。

例如(我必须删除文件类型才能将对象传递给测试功能):

def mockFile = new MockFor(java.io.File)

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

或者(使用元类):

File mockFile = new File("irrelevant_path")
mockFile.metaClass.eachFile = {[new File("script1.sql"), new File("script2.syn"), new File("script3.grt")].each {it}}

我的 eachFile 方法定义为:

public static void eachFile(final File self, final Closure closure) throws FileNotFoundException, IllegalArgumentException {
        eachFile(self, FileType.ANY, closure);
    }

对于所有模拟这个的编码尝试,我已经有点模糊了:)

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

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

folderSourceScripts.eachFile {File currentFile -> ..... }

在 Java 中,Mockito 会在一分钟内完成此操作,但我在某处看到与 Groovy 集成存在一些问题。模拟类时出现问题,因为 Groovy 调用了元类。

我看到了这个here

tim_yates 写道:

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,并且文件变量是在一个方法中传递的。 因此,以您编写它的方式使用它会导致:

groovy.lang.MissingMethodException: No signature of method: groovy.mock.interceptor.MockFor.eachFile() is applicable for argument types: ... 

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

测试中的代码如下所示:

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)

理论上它可以工作,但在这个例子中它失败了,也许我编码错了。我两周前开始使用 Groovy,所以我还是习惯了。 谢谢

【问题讨论】:

    标签: java groovy


    【解决方案1】:

    tim_yates 写道:

    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 的时间不长(Spock 也没有)。

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

    测试中的代码如下所示:

    when:
    
            mock.use {
              folderValidator.validate(new File("."))
            }
    
    then:
            folderValidator.listMissingFiles.size == 3
    

    解决方案是简单地在 use 块内实例化模拟类。我认为 mock 已实例化,并将在方法中传递 - Mockito 的工作方式。

    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

    【讨论】:

    • 这是可行的,因为 File 有一个单参数构造函数。多参数构造函数呢?
    • 应该同样工作吗?我真的不记得所有的细节,但我认为它应该工作得很好。如果您无法模拟它,我建议您将所需的模拟隐藏在界面后面。 FileFactory 接口与 File create(... desired params ...) 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    相关资源
    最近更新 更多