我试图模拟循环中生成的新文件。简化示例:
class FileClass {
def basePath
def listObjects = []
def createFilePerObject() {
listObjects.each {currentObject ->
File currentFile = new File("${basePath.toString()}/${currentObject.objectName}")
currentFile.write currentObject.objectContent //Verify this behaviour!!
}
}
}
class SimpleObject {
String objectName
String objectContent
}
而且,测试:
class FileClassTest extends Specification {
FileClass fileClass
def "test simple object"() {
def listObjects = []
SimpleObject object1 = new SimpleObject(objectName: "First object", objectContent: "First object content")
SimpleObject object2 = new SimpleObject(objectName: "Second object", objectContent: "Second object content")
SimpleObject object3 = new SimpleObject(objectName: "Third object", objectContent: "Third object content")
SimpleObject object4 = new SimpleObject(objectName: "Fourth object", objectContent: "Fourth object content")
listObjects << object1
listObjects << object2
listObjects << object3
listObjects << object4
fileClass = new FileClass(listObjects: listObjects, basePath: ".")
def dummyFile = new MockFor(File)
def mockFile = new MockFor(File, true) //Intercept constructor call
mockFile.demand.with {
File() {dummyFile}
}
when:
mockFile.use {
fileClass.createFilePerObject()
}
then:
1 * mockFile.write(_)
}
}
因此,正如您所看到的,我正在尝试验证新文件实际上是否有内容写入。
并且,我收到以下错误:
MockFor with constructor interception enabled is only allowed for Groovy objects but found: java.io.File
因此,据我所知,File在Groovy GDK(Groovy JDK)中进行了扩展,并且它还有其他(并且非常有用)方法。但是Groovy试图模拟java.io.File。
并且,根据错误的逻辑,我决定实际上像这样删除File构造函数:
class FileClassTest extends Specification {
FileClass fileClass
def "test simple object"() {
def listObjects = []
SimpleObject object1 = new SimpleObject(objectName: "First object", objectContent: "First object content")
SimpleObject object2 = new SimpleObject(objectName: "Second object", objectContent: "Second object content")
SimpleObject object3 = new SimpleObject(objectName: "Third object", objectContent: "Third object content")
SimpleObject object4 = new SimpleObject(objectName: "Fourth object", objectContent: "Fourth object content")
listObjects << object1
listObjects << object2
listObjects << object3
listObjects << object4
fileClass = new FileClass(basePath: ".", listObjects: listObjects)
def mockFile = new MockFor(File)
File.metaClass.constructor << {String filePath -> mockFile } //Return the mocked file, so it can be verified
when:
mockFile.use {
fileClass.createFilePerObject()
}
then:
1 * mockFile.write(_)
}
}
并且收到了构造函数已经存在的警告(我想我毕竟不能再这样做了):
groovy.lang.GroovyRuntimeException: Cannot add new constructor for arguments [[class java.lang.String]]. It already exists!
因此,其中一个想法是实际模拟将在循环中生成新File对象的File Factory。但是,工厂至少可以说是无用的 - 它只能用于测试文件创建的能力。
所以,PowerMock不起作用(无法加载PowerMockRunner),任何想法如何模拟这个,不使用额外的库,而不是最终无用的类?
感谢。
答案 0 :(得分:1)
我可以建议其他非纯测试方法。
对于这个测试,创建一个临时目录,在测试主题中设置basePath
并允许测试实际写出文件。您的断言显然已经读取了文件以验证结果,但它将是一个完整的测试而不试图模拟JDK类。然后,测试拆解可以清理临时目录。
如果你真的开始进行内存单元测试,我恐怕你可能不得不使用JMockIt,如果你可以了解它并且文档可以模拟任何东西,包括部分内容JDK。