在“ when”块中运行Platform.runLater()的Spock计时问题

问题描述 投票:0回答:1

如果必须在JavaFX线程中调用方法,则看来我必须在when块中执行以下操作:

... setup ...
// def throwable

when:
Platform.runLater( new Runnable(){
    @Override
    void run() {
        // try {
        log.debug "in runnable, calling run method ..."
        someObject.methodWhichMustRunInJavaFXThread()
        log.debug "... run method finished normally"
        // }catch( Throwable t ){
        //     log.error( t.message, t )
        //     throwable = t
        // }
    }
})
WaitForAsyncUtils.waitForFxEvents()
log.debug "waitForFXEvents ended..."
// if throwable != null 
//     throw throwable
/* NB it appears that re-throwing the Throwable like this after waitForFxEvents
is probably the only way to bring it to the developer's attention! 
PS I added this re-throwing idea only a few hours after submitting the question. I am 
currently monitoring things to find whether this in fact solves the problem */

then:
// throwable == null 
/* in fact this seems to be a rather naive check: from my experimentation, 
regardless of whether caught in the above catch clause, it appears that if a throwable
is thrown in `run`, although "invocation counting tests" are performed in the "then" 
block, this sort of "static" equality check will never be performed in the "then" block
*/
... other verifications...

但是我断断续续地发现,如果在run方法中引发异常,则这种技术可能导致失败的可怕泄漏到后续测试。我认为,尝试取消任何注释行,如上面的代码所示,可以解决任何问题,但实际上不行:实际上是:在run中抛出并由catch子句捕获的throwable ,仍然可以归因于以后的方法!

这是一种误导性的Spock失败输出的示例:尽管此NPE在先前的测试方法中被抛出在Platform.runLater( ... )中(实际上是在文件initial_load_testing.groovy中完全不同的Specification中),但是此失败实际上归因于一个测试,该测试恰好在它之后的任意时间出现。

注意,提到“延迟异常” ...

java.lang.RuntimeException: java.lang.NullPointerException: Cannot invoke method setRoot() on null object
    at org.testfx.util.WaitForAsyncUtils.---- Delayed Exception: (See Trace Below) ----(WaitForAsyncUtils.java:0)
Caused by: java.lang.NullPointerException: Cannot invoke method setRoot() on null object
    at core.FileHandlingFramework.tryToLoadFile(filehandlingframework.groovy:83)
    at core.StdFileHandlingFrameworkTemplate.tryToOpenFile(stdfilehandlingframeworktemplate.groovy:97)
    at core.App.start(main.groovy:120)
    at core.AppStdSpec2$1.run(initial_load_testing.groovy:92)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    at java.base/java.lang.Thread.run(Thread.java:834)

[我发现奇怪的是,我确实允许JavaFX线程事件与WaitForAsyncUtils.waitForFxEvents()发生“冲突” ...但是,似乎在某种程度上Spock框架有时可以检测到可抛出对象的抛出。 waitForFXEvents()方法结束。

有解决方案吗?现象的间歇性是一个实际问题。

java javafx groovy thread-safety spock
1个回答
0
投票

临时,以下解决方案出现可以通过在when块结束之前重新抛出FX线程中捕获的任何异常来起作用:

... setup ...
def throwable

when:
Platform.runLater( new Runnable(){
    @Override
    void run() {
        try {
            someObject.methodWhichMustRunInJavaFXThread()
        }catch( Throwable t ){
            log.error( t.message, t )
            throwable = t
        }
    }
})
WaitForAsyncUtils.waitForFxEvents()
if throwable != null 
    throw throwable

如chrylis -onstroke-所述,也可以使用闭包,因此实用程序方法可能如下所示:

void executeInFXThreadAndWait( def closure, def ... params ){
    def fXThrowable
    Platform.runLater({ it ->
        try {
            closure(params)
        }catch( Throwable t ){
            if( t.message != 'exit' ) {
                log.error(t.message, t)
                fXThrowable = t
            }
        }
    })
    WaitForAsyncUtils.waitForFxEvents()
    if( fXThrowable != null )
        throw fXThrowable
}

用法(App扩展为Application):

def myClosure = { args ->
    App.instance.start( args[ 0 ] )
}
...
TestUtilities.instance.executeInFXThreadAndWait( myClosure, mockStage )

NB关于测试“退出”的事情是,有时我故意在测试中抛出异常,以从需要验证的方法已经被验证的方法“弹出”。如果Throwable的消息为“退出”,它将被忽略。

假说:我猜测,Spock框架不知不觉中能够检测到异常是否已经“处理完毕”,并且如果这样重新抛出该异常,那么该框架将不会继续处理“延迟异常” 。欢迎Spock专家发表评论。

© www.soinside.com 2019 - 2024. All rights reserved.