Spock测试绿色,虽然应用程序代码抛出异常

时间:2018-02-02 09:49:26

标签: groovy junit nullpointerexception spock

我正在使用Groovy和Gradle进行测试。

我的应用代码中有以下几行:

Platform.runLater( new Runnable() {
    void run() {
    ....

        FileChooser fc = getFileChooser()
        File file = fc.showOpenDialog( null )

        // if( file != null && file.exists() ) { <--- this is what I have to put
        if( file.exists() ) { 
            println( "file $file exists")
            analyseFile( file )
        }

如果我嘲笑(使用GroovyMock,因为javafx.stage.FileChooserfinal),以便fc.showOpenDialog返回null,我希望NullPointerException成为file.exists()抛出Runnable ......一个是。

但是这并没有出现在测试结果中,这些结果都是绿色的。你发现这种情况的唯一方法是当你去看看课程的测试结果时:然后你会看到灰色按钮说&#34; StdErr&#34;在场。

这似乎是因为包围Runnable是&#34;吞咽&#34;它...

Spock有没有办法在def "getting a null result from the showOpenDialog should be handled OK"(){ given: FileChooser fc = GroovyMock( FileChooser ) ConsoleHandler ch = Spy( ConsoleHandler ){ getFileChooser() >> fc } ch.setMaxLoopCount 10 systemInMock.provideLines( "o" ) fc.showOpenDialog( _ ) >> null when: com.sun.javafx.application.PlatformImpl.startup( {} ) ch.loop() Thread.sleep( 1000L ) // NB I know this is a rubbish way to handle things... but I'm a newb with Spock! then: 0 * ch.analyseFile( _ ) } 导致测试失败的情况下做出异常?

PS测试代码:

class ConsoleHandler {
    int loopCount = 0
    def maxLoopCount = Integer.MAX_VALUE - 1
    def response
    FileChooser fileChooser = new FileChooser()

    void analyseFile( File file ) {
        // ...
    }
    void loop() {
        while( ! endConditionMet() ){
            print '> '
            response = System.in.newReader().readLine()
            if( response ) response = response.toLowerCase()
            if( response == 'h' || response == 'help' ){
                println "Help: enter h for this help, q to quit"
            }
            else if ( response == 'o' ){
                Platform.runLater( new Runnable() {
                    void run() {
                        FileChooser fc = getFileChooser()
                        File file = fc.showOpenDialog( null )
                        // if( file != null && file.exists() ) {
                        if( file.exists() ) {
                            analyseFile( file )
                        }
                    }
                })
            }
        }
    }
    boolean endConditionMet() {
        loopCount++
        response == 'q' || loopCount > maxLoopCount
    }
    static void main( args ) {
        com.sun.javafx.application.PlatformImpl.startup( {} )
        new ConsoleHandler().loop()
        com.sun.javafx.application.PlatformImpl.exit()
    }
}

这里是应用代码的SSCCE

systemInMock

可能需要解释的唯一另一件事是Spock测试代码中的StdIn,它允许测试在应用代码中将文本提供给import org.junit.contrib.java.lang.system.TextFromStandardInputStream import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream .... // field of the Test class, of course: @Rule public TextFromStandardInputStream systemInMock = emptyStandardInputStream()

dependencies

我的Gradle testCompile 'com.github.stefanbirkner:system-rules:1.16.0' 子句中的相应行是:

@Grab

...但我认为这可以通过在Groovy测试文件中使用Platform来获得,对吧?

我想我现在意识到这个问题真的是关于如何最好地在Spock中进行JavaFX-app线程测试...使用Swing进行EDT测试总是一个问题,毫无疑问类似的事情也适用。它全部回到我身边:当你Runnable运行runLater时,当调用者代码移动时从run()抛出异常是没有意义的,所以我认为唯一可行的选择是export class ChildComponent implements OnInit { private _foo : Foo; @Input() set foo(value : Foo) { this._foo = Object.create(value || null); } get foo() : Foo { return this._foo; } @Output() onChange : EventEmitter<Foo> = new EventEmitter<Foo>(); constructor() { } ngOnInit() { } } 调用测试代码可以调用的其他方法......

我已经搜索过&#34; Spock JavaFX测试&#34;但是没有多少出现......

1 个答案:

答案 0 :(得分:0)

这是我想象的唯一实用的前进方式:改变这一点:

else if ( response == 'o' ){
    Platform.runLater(new Runnable() {
        void run() {
            openFileChooser()
        }
    })
}

ConsoleHandler的新方法:

def openFileChooser() {
    FileChooser fc = getFileChooser()
    File file = fc.showOpenDialog( null )
    // if( file != null && file.exists() ) {
    if( file.exists() ) {
        analyseFile( file )
    }
}

新的Spock测试:

def "getting a null result from the showOpenDialog should be handled OK2"(){
    given:
    FileChooser fc = GroovyMock( FileChooser )
    ConsoleHandler ch = Spy( ConsoleHandler ){ getFileChooser() >> fc }
    fc.showOpenDialog( _ ) >> null

    when:
    com.sun.javafx.application.PlatformImpl.startup( {} )
    ch.openFileChooser()
    Thread.sleep( 1000L )

    then:
    0 * ch.analyseFile( _ )
}

测试失败(欢呼!):

  

java.lang.NullPointerException:无法在null上调用exists()方法   对象

但我欢迎来自更有经验的Groovy / Spock手的改进是否可以改进。

确实我有点疑惑为什么我没有得到错误的状态&#34;当我在openFileChooser子句中调用when:时。我认为这是因为在模拟 showOpenDialog上进行FileChooser实际上并不涉及任何检查,以确保我们目前在JavaFX-app-中线。事实证明,在该测试中可以删除...PlatformImpl.startup( {} )Thread.sleep行。这是理想的做法吗?!嗯...

<强>
将此视为唯一的答案......实际上,在JavaFX-app-thread中使用普通的JUnit测试普通旧Java中的代码时,同样的注意事项也适用于此问题。 Spock + Groovy可能会带来一些问题,或者可能会让它变得更容易......我还没有足够的经验让他们知道。