1

File Factory を使用して File オブジェクトの構築を模擬することにしました。

class FileClass {

  def basePath
  def listObjects = []

  def createFilePerObject() {
    listObjects.each {currentObject ->
      // Use some other libraries for mocking(cant run PowerMockito, Gareth Davis adviced me to use JMockit)

      // File currentFile = new File("${basePath.toString()}/${currentObject.objectName}")

      //File factory(The simplest of the solutions)...
      File currentFile = FileFactory.makeFile("${basePath.toString()}/${currentObject.objectName}")

      currentFile.write currentObject.objectContent   //Verify this behaviour!!
    }
  }

}

class SimpleObject {
  String objectName
  String objectContent
}

//Really simple
class FileFactory {
  def static makeFile(String pathFileName) {
    return new File(pathFileName);
  }
}

そしてテスト:

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 mockFile = Mock(File)

    def mockFileFactory = new MockFor(FileFactory)
    mockFileFactory.demand.makeFile {mockFile}    //Return the mocked file...

    when:
    mockFileFactory.use {
      fileClass.createFilePerObject()
    }

    then:
    1 * mockFile.write(_)
  }

}

問題は、NullPointerException で失敗することです!?

私が得たデバッガを使用して:

currentFile.write currentObject.objectContent   //Verify this behaviour!!

そして、確認されたように、「現在のファイル」は実際にはテストで指定されたモック ファイルです。「currentObject.objectContent」は null ではなく、「currentFile」は null ではありません。

突然、次のメソッドの BaseSpecRunner.java にジャンプします。

protected Object invokeRaw(Object target, MethodInfo method, Object[] arguments) {
    if (method.isStub()) return null;

    try {
      return method.getReflection().invoke(target, arguments);
    } catch (InvocationTargetException e) {
      //Here it fails!
      runStatus = supervisor.error(new ErrorInfo(method, e.getTargetException()));
      return null;
    } catch (Throwable t) {
      Error internalError =
          new InternalSpockError("Failed to invoke method '%s'", t).withArgs(method.getReflection().getName());
      runStatus = supervisor.error(new ErrorInfo(method, internalError));
      return null;
    }
  }

「InvocationTargetException は、呼び出されたメソッドまたはコンストラクターによってスローされた例外をラップするチェック済み例外です。」. 偉大な。

何か案は?

ありがとう。

4

2 に答える 2

3

File.write()Spock は現在、Groovy によって動的に追加されるものの、クラスには存在しないようなモッキング メソッドをサポートしていません。この問題MockForは、他のモックで行ったように、代わりに Groovy を使用することで解決できます。

InvocationTargetExceptionGroovy の内部例外です。NullPointerExceptionそれはあなたが見ているものを包み込みます。Spock は賢く、例外をアンラップします。

于 2011-02-24T15:41:38.793 に答える
2

ピーター、あなたは正しかった。固定テストは次のとおりです。

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 mockFile = new MockFor(File)

    //This is how i can verify that the write method was called 4 times(no more, no less)
    // but im not using Spock and some of the advanced verification abilites that come with it...
    mockFile.demand.write(4) {}

    def mockFileFactory = new MockFor(FileFactory)
    mockFileFactory.demand.makeFile(4) {new File(".")}    //Fixed.

    when:
    mockFile.use {
      mockFileFactory.use {
        fileClass.createFilePerObject()
      }
    }
    then:
//    1 * mockFile.write(_)

    //Just pass... Verification is done by MockFor, not Spock
    true
  }
}

ただし、これは以前のテスト方法とさらに「調和」していることがわかりました。

class FileClassTest extends Specification {

  class FileCustomWrapper extends File {

    def FileCustomWrapper(String pathname) {
      super(pathname);
    }

    //Ovveride the DefaultGroovyMethods method, Spock can recognize it, its staticly written
    // , and ovveriden only for the use of mocking...

    def write(String s) {
      metaClass.write(s)
      //super.write(s)
    }
  }

  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 mockFile = Mock(FileCustomWrapper)

    def mockFileFactory = new MockFor(FileFactory)
    mockFileFactory.demand.makeFile(4) {mockFile}     //Pass the Spock mock

    when:
    mockFileFactory.use {
      fileClass.createFilePerObject()
    }

    then:
    //You can use the verification...
    4 * mockFile.write(_)
  }
}

そのため、Spock を使用して、Groovy によって動的に追加されたメソッドを、カスタムの「ラッパー」クラスでオーバーライドすることによってモックすることができます。

于 2011-02-25T11:31:06.617 に答える