如何在Spock中模拟Groovy的eachDir闭包方法?
在Spock中正确模拟File类的eachDir闭包方法
你碰到的问题核心在于:eachDir不是java.io.File类的原生方法,而是Groovy GDK给File类添加的扩展方法,所以直接在Mock(File)里定义eachDir()的行为是行不通的。不过我们可以通过mock它底层依赖的原生方法来实现需求,下面是具体的解决办法:
解决方案思路
Groovy的File.eachDir()方法本质上是调用了File.listFiles(FileFilter),筛选出目录类型的文件后,依次传入闭包执行。所以我们只需要mocklistFiles()方法返回预先准备好的mock子目录数组,eachDir()就能自动按照预期工作了。
正确的Mock代码示例
def mockSubdirs = [] mockSubdirs << Mock(File) { getName() >> 'some subdir' lastModified() >> 2000 isDirectory() >> true // 关键:标记为目录,这样eachDir才会识别它 } // 可以再加一个子目录示例 mockSubdirs << Mock(File) { getName() >> 'another subdir' lastModified() >> 3000 isDirectory() >> true } File mockParentDir = Mock(File) { getName() >> 'parent dir' // mock原生的listFiles方法,返回我们的mock子目录数组 listFiles() >> mockSubdirs.toArray(new File[0]) } cut.myDirectory = mockParentDir
验证测试的应用代码示例
假设你的应用代码是这样遍历目录的:
def dirNames = [] myDirectory.eachDir { dir -> dirNames << dir.name }
那么在测试里你可以这样断言:
expect: dirNames == ['some subdir', 'another subdir']
额外注意点
- 一定要给mock的子目录设置
isDirectory() >> true,因为eachDir只会筛选出目录类型的文件,否则这些mock文件会被忽略。 - 对于GDK的扩展方法,优先mock它依赖的原生JDK方法,这比直接mock扩展方法要简单可靠得多,因为扩展方法通常是基于原生方法实现的。
内容的提问来源于stack exchange,提问作者mike rodent
相关产品推荐
相关产品推荐

