测试Kotlin控制台时要注入哪个Coroutine调度员

发布于 2025-02-09 19:16:41 字数 819 浏览 2 评论 0原文

我有一个后端Springboot Kotlin应用程序,该应用具有一些简单的Coroutine代码,用于并行IO操作。 现在看起来像这样的

@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())
    }
  }
}

产品,我可以注入dispatchers.io调度器,一切正常。但是,在测试时,我不需要多线程。我想注入dispatcher.main,但它是针对Android应用的。另外,我想什么都不注入,让范围从父属继承并在主线程上运行,runblocking {}在没有任何参数的情况下工作。但是我不知道该怎么做。我应该使用dispatchers.uncondined吗?据我了解,除非我明确地旋转另一个线程,否则它将留在主线程上。

这里的标准做法是什么?

I have a back-end springboot Kotlin app that has some simple coroutine code for parallel IO operations. 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. However when testing I don't want multithreading. I want to inject Dispatcher.Main but it's meant for android apps. 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. But I can't figure out how to do that. Should I be using 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

厌倦 2025-02-16 19:16:41

另外,我想什么都不注入,让范围从父属继承并在主线程上运行,而runblocking {}的方式无需任何参数。但是我不知道该怎么做

但是,如果您控制了getAccount()在这里, >在此级别。如果您只是在项目中介绍Coroutines,那当然可以作为第一步,但是我鼓励您尽快继续上呼叫堆栈。这样,您将从上下文继承中受益,并避免将线程从其他Coroutines决定调用您的服务。

现在,您可以使用kotlinx-coroutines测试进行测试,它们提供可以使用的测试调度程序,甚至可以控制虚拟时间和测试超时等。但是,请注意,请注意,这是由于虚拟时间,您无法将这种调度程序用于调用不属于虚拟时间的实际系统(例如某些外部服务,或者仅使用硬编码的非测试调度器)的代码。

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. 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. 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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文