不使用TestCoroutineDispatcher或TestCoroutineScope来处理协程测试异常 [英] Coroutines Test exception is not handled with neither TestCoroutineDispatcher nor TestCoroutineScope

查看:113
本文介绍了不使用TestCoroutineDispatcher或TestCoroutineScope来处理协程测试异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用此手册来测试协同程序.编写预期会引发异常的测试会崩溃,而不是通过测试.我不知道我在做什么错.

Using this manual to test Coroutines. Writing a test that expected to throw exception crashes instead of passing the test. I wonder what i'm doing wrong.

    private val testDispatcher = TestCoroutineDispatcher()

    @Before
    fun setup() {
        // provide the scope explicitly, in this example using a constructor parameter
        Dispatchers.setMain(testDispatcher)
    }

    @After
    fun cleanUp() {
        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }

    @Test(expected = RuntimeException::class)
    fun testSomeFunctionWithException() = testDispatcher.runBlockingTest {
        someFunctionWithException()
    }


    private fun someFunctionWithException() {
        MainScope().launch {
            throw RuntimeException("Failed via TEST exception")
        }
    }

上面的测试方法和下面的测试方法

The test method above and the one below

    private val testScope = TestCoroutineScope()
    private lateinit var subject: Subject

    @Before
    fun setup() {
        // provide the scope explicitly, in this example using a constructor parameter
        subject = Subject(testScope)
    }

    @After
    fun cleanUp() {
        testScope.cleanupTestCoroutines()
    }


    @Test(expected = RuntimeException::class)
    fun testFooWithException() = testScope.runBlockingTest {
        subject.fooWithException()
    }

    class Subject(private val scope: CoroutineScope) {


        fun fooWithException() {
            scope.launch {
                println("fooWithException() thread: ${Thread.currentThread().name}")
                throw RuntimeException("Failed via TEST exception")
            }
        }
    }

尽管它们都崩溃了

注意:不复杂时,最好提供TestCoroutineScope 代码,因为它还会提升异常以测试失败.

Note: Prefer to provide TestCoroutineScope when it does not complicate code since it will also elevate exceptions to test failures.

  1. 为什么他们两个都崩溃了?
  2. 为什么具有作用域的对象不会失败而不是崩溃?

推荐答案

TestCoroutineScope使用TestCoroutineExceptionHandler可以处理协程中引发的所有异常,并将它们收集在uncaughtExceptions列表中,尽管第一个异常将被重新抛出在cleanUp或更确切地说是在调用cleanupTestCoroutines()时,因此您必须对该异常做一些事情,以防止测试失败.

TestCoroutineScope uses TestCoroutineExceptionHandler which will handle all the exceptions thrown in the coroutine collecting them in the uncaughtExceptions list, although the first one will be rethrown during cleanUp or more specifically when cleanupTestCoroutines() is called, so you have to do something about that exception to prevent failing the tests.

@After
fun cleanUp() {
    try {
        testScope.cleanupTestCoroutines()
    } catch (e: Exception) {
        //Do something here
    }
}

在测试过程中,您可以检查uncaughtExceptions列表以做出结论:

During the tests you can inspect the uncaughtExceptions list in order to make your assertions:

@Test(expected = RuntimeException::class)
fun testFooWithException() = testScope.runBlockingTest {
    subject.fooWithException()
    assertEquals(1, uncaughtExceptions.size)
    assertEquals(uncaughtExceptions[0].message, "Failed via TEST exception")
}

这篇关于不使用TestCoroutineDispatcher或TestCoroutineScope来处理协程测试异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆