当action调用runAsync时,java.util.concurrent.RejectedExecutionException

时间:2018-01-30 02:19:17

标签: javafx tornadofx testfx

我注意到在将我的TornadoFX版本从1.7.12升级到1.7.14时,我的一个测试破了。当被测runAsyncWithProgress中的View被状态为ThreadPoolExecutor的{​​{1}}拒绝时,事情似乎就会失控。我在1.7.13的发行说明中看到有一个更改“内部线程池在应用程序退出时关闭”。将TornadoFX版本设置为1.7.13导致同样的失败,这证实了我怀疑它与上述变化有关。

我写了一个简单的应用程序来演示这个错误。

Terminated

和测试

// src/main/kotlin/me/carltonwhitehead/AsyncBugApp.kt
class AsyncBugApp : App(MainView::class)

/**
 * The main method is needed to support the mvn jfx:run goal.
 */
fun main(args: Array<String>) {
    Application.launch(AsyncBugApp::class.java, *args)
}

class MainView : View("Async Bug App") {
    val controller: MainController by inject()
    override val root = pane {
        button("Robot-click to repeat bug") {
            id = "bug"
            action {
                runAsync {
                    controller.onAction("button clicked")
                }
            }
        }
    }
}

class MainController : Controller() {
    fun onAction(message: String) {
        println(message)
    }
}

第一次执行测试时,它会通过。第二次,它会挂起,因为runAsync被以下堆栈跟踪拒绝。

// src/test/kotlin/me/carltonwhitehead/AsyncBugAppTest.kt
@RunWith(Parameterized::class)
class AsyncBugAppTest(val rounds: Int) {

    companion object {
        @JvmStatic
        @Parameterized.Parameters
        fun data() : Collection<Array<Int>> {
            return listOf(arrayOf(1), arrayOf(1))
        }
    }

    lateinit var robot: FxRobot
    lateinit var app: App

    @RelaxedMockK
    lateinit var controller: MainController

    @Rule @JvmField
    val timeout = Timeout(10, TimeUnit.SECONDS)

    @Before
    fun before() {
        MockKAnnotations.init(this)

        FxToolkit.registerPrimaryStage()
        app = AsyncBugApp()
        app.scope.set(controller)
        FxToolkit.setupApplication { app }
        robot = FxRobot()
        println("rounds = $rounds")
    }

    @After
    fun after() {
        FxToolkit.cleanupStages()
        FxToolkit.cleanupApplication(app)
    }

    @Test()
    fun itShouldSurviveRunAsyncMultipleTimes() {
        val latch = CountDownLatch(rounds)
        every { controller.onAction(any()) }.answers { latch.countDown() }

        var i = 0
        while(i <= rounds) {
            robot.clickOn("#bug")
            i++
        }

        latch.await()
        verify(exactly = rounds) { controller.onAction(any()) }
    }
}

我怀疑我可能在TestFX / TornadoFX应用程序生命周期中出错了。每个测试周期都在创建一个新的app实例,所以我很困惑为什么会保留ThreadPoolExecutor。有什么建议吗?

回复https://github.com/carltonwhitehead/fx-async-bug-test

0 个答案:

没有答案