How can I fail a JUnit Test from within a test rul

2019-06-27 02:36发布

问题:

I have some async code that may throw an exception that JUnit misses (so the test passes).

I've created a TestRule to collect those exceptions into a list. After any test has finished, an assertion runs over the list and fails the test if the exception list is non-empty.

Instead of failing after the test finishes, I would like to fail the test immediately when the exception occurs. Is this possible to do this with a TestRule?

My TestRule

/**
 * Coroutines can throw exceptions that can go unnoticed by the JUnit Test Runner which will pass 
 * a test that should have failed. This rule will ensure the test fails, provided that you use the 
 * [CoroutineContext] provided by [dispatcher].
 */
class CoroutineExceptionRule : TestWatcher(), TestRule {

    private val exceptions = Collections.synchronizedList(mutableListOf<Throwable>())

    val dispatcher: CoroutineContext
        get() = Unconfined + CoroutineExceptionHandler { _, throwable ->
            // I want to hook into test lifecycle and fail test immediately here
            exceptions.add(throwable)
            // this throw will not always fail the test. this does print the stacktrace at least
            throw throwable
        }

    override fun starting(description: Description) {
        exceptions.clear()
    }

    override fun finished(description: Description) {
        // instead of waiting for test to finish to fail it
        exceptions.forEach { throw AssertionError(it) }
    }
}