Spock:使用 GroovyMock 进行不需要的真实方法调用



>我有这样的测试

def "fileField should be set for each line batch"(){
given:
LuceneEngine le = new LuceneEngine()
le.indexWriter = Mock( IndexWriter ){
addDocument(_) >> null 
}
le.currentFilename  = 'dummy filename'
le.fileField = GroovyMock( TextField )
when:
le.processLineBatch([ 'dummy text' ], 0 )
then:
1 * le.fileField.setStringValue( 'dummy filename' ) >> null         
}

应用方法如下所示:

def processLineBatch( List lineBatch, int deliveryNo ) {
String lDocText = lineBatch.join( 'n' ).trim()
textField.setStringValue( lDocText )
fileField.setStringValue( currentFilename )
indexWriter.addDocument( singleLDoc )
}

我必须使用GroovyMock进行TextField,因为该类final

无论我做什么(我已经尝试了很多事情),实际的方法setStringValue运行......然后生成一个Exception,因为这是一个模拟。

有关信息,失败如下所示:

java.lang.NullPointerException
at org.apache.lucene.document.Field.setStringValue(Field.java:307)
at org.spockframework.mock.runtime.GroovyMockMetaClass.doInvokeMethod(GroovyMockMetaClass.java:86)
在 org.spockframework.mock.runtime.GroovyMockMetaClass.invokeMethod(GroovyMockMetaClass.java:42)
在核心。LuceneEngine.processLineBatch(lucene_functions.groovy:422)

。其中 422 行是行fileField.setStringValue (...

这似乎与我对非Groovy模拟的期望相反。谁能解释一下我做错了什么以及是否有解决方案?

Lucene 6 中的 NBTextField在这里...从中您可以链接到超类Field并看到setStringValue是(非final)public void

实际上你基本上已经问了同样的问题,你甚至接受了我的答案!你需要使用一个全局的Groovy模拟:

package de.scrum_master.stackoverflow
import org.apache.lucene.document.TextField
import org.apache.lucene.index.IndexWriter
import org.apache.lucene.index.IndexableField
class LuceneEngine {
TextField textField
TextField fileField
IndexWriter indexWriter
String currentFilename
Iterable<? extends IndexableField> singleLDoc
def processLineBatch(List lineBatch, int deliveryNo) {
String lDocText = lineBatch.join('n').trim()
textField.setStringValue(lDocText)
fileField.setStringValue(currentFilename)
indexWriter.addDocument(singleLDoc)
}
}
package de.scrum_master.stackoverflow
import org.apache.lucene.document.TextField
import org.apache.lucene.index.IndexWriter
import spock.lang.Specification
class LuceneEngineTest extends Specification {
def "fileField should be set for each line batch"() {
given:
LuceneEngine le = new LuceneEngine()
le.indexWriter = Mock(IndexWriter) {
addDocument(_) >> null
}
le.currentFilename = 'dummy filename'
// Assign this to le.textField or le.fileField if you like, it does not
// make a difference because the Groovy mock is GLOBAL
GroovyMock(TextField, global: true)
when:
le.processLineBatch(['dummy text'], 0)
then:
1 * le.fileField.setStringValue('dummy filename') >> null
}
}

至于为什么你需要在这里使用全局模拟,我无法解释。这是斯波克邮件列表的问题。我再次完成了您的工作并在那里发布了一个问题。

最新更新