简体   繁体   English

测试 Kotlin 控制台时注入哪个协程调度程序

[英]Which coroutine dispatcher to inject when testing a Kotlin console

I have a back-end springboot Kotlin app that has some simple coroutine code for parallel IO operations.我有一个后端 springboot Kotlin 应用程序,其中包含一些用于并行 IO 操作的简单协程代码。 It looks something like this它看起来像这样

@Service
class AccountService(
    private val client: ApiClient
    private val coroutineDispatcher: CoroutineDispatcher
) {

  fun getAccount(): AccountDTO {

    return runBlocking(coroutineDispatcher) {
      val foo = async {
        client.getFoo() //some long operation
      }

      val bar = async {
        client.getBar() //some other operation
      }

      AccountDTO(foo.await(), bar.await())
    }
  }
}

Now in production I can inject let's say a Dispatchers.IO dispatcher and everything works fine.现在在生产中,我可以注入一个Dispatchers.IO调度程序,一切正常。 However when testing I don't want multithreading.但是在测试时我不想要多线程。 I want to inject Dispatcher.Main but it's meant for android apps.我想注入Dispatcher.Main但它适用于 android 应用程序。 Alternatively I'd like to inject nothing and let the scope inherit from the parent and run on the main thread, the way runBlocking{} works without any arguments.或者,我不想注入任何内容,让范围从父级继承并在主线程上运行, runBlocking{}的工作方式没有任何参数。 But I can't figure out how to do that.但我不知道该怎么做。 Should I be using Dispatchers.Unconfined ?我应该使用Dispatchers.Unconfined吗? From what I understand it will stay on the main thread unless I spin up another thread myself explicitly.据我了解,除非我自己明确启动另一个线程,否则它将保留在主线程上。

What's the standard practice here?这里的标准做法是什么?

Alternatively I'd like to inject nothing and let the scope inherit from the parent and run on the main thread, the way runBlocking{} works without any arguments.或者,我不想注入任何内容,让范围从父级继承并在主线程上运行,runBlocking{} 的工作方式没有任何参数。 But I can't figure out how to do that但我不知道该怎么做

If you have control over getAccount() here, you should make this one suspend and avoid runBlocking at this level.如果您在此处可以控制getAccount() ,则应将其suspend并避免在此级别runBlocking If you're just introducing coroutines in the project, it's of course fine like this as a first step, but I would encourage you to keep going up the call stack soon.如果您只是在项目中引入协程,那么第一步当然可以,但我鼓励您尽快继续调用调用堆栈。 This way you'll benefit from context inheritance and avoid blocking threads from other coroutines if they decide to call your service.这样,您将受益于上下文继承,并避免在其他协程决定调用您的服务时阻塞线程。

Now, you could use kotlinx-coroutines-test for your tests, they provide test dispatchers that you can use, which even allow you to control virtual time and test timeouts etc. Note, however, that due to the virtual time, you cannot use this kind of dispatcher for code that calls an actual system that's not part of virtual time (like some external service, or just a piece of code using a hardcoded non-test dispatcher).现在,您可以使用kotlinx-coroutines-test进行测试,它们提供了您可以使用的测试调度程序,甚至可以让您控制虚拟时间和测试超时等。但是请注意,由于虚拟时间,您不能使用这种调用不属于虚拟时间的实际系统的代码调度程序(例如某些外部服务,或者只是使用硬编码的非测试调度程序的一段代码)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM