java 如何对 ExecutorService 为任务生成新线程进行单元测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1669453/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 17:31:29  来源:igfitidea点击:

How to unit test that ExecutorService spawns new thread for task?

javamultithreadingconcurrency

提问by Ben Simmons

How does one unit test that a new thread was spawned for a Runnable task when using an ExecutorService?

使用 ExecutorService 时,一个单元如何测试为 Runnable 任务生成了一个新线程?

Basically, I have a static thread pool for my application.

基本上,我的应用程序有一个静态线程池。

public static final ExecutorService executorService = Executors.newCachedThreadPool();

I'd like to use this thread pool for the my unit tests, rather than mocking one out or injecting a new thread pool, since different thread pools can dramatically alter the behavior of my application (fixed vs. cached vs. scheduled, etc); I want to ensure that I test the application's behavior with its run-time thread pool.

我想在我的单元测试中使用这个线程池,而不是模拟一个或注入一个新的线程池,因为不同的线程池可以显着改变我的应用程序的行为(固定、缓存、调度等) ; 我想确保我使用其运行时线程池测试应用程序的行为。

Cached thread pool seems to work best for me. The problem is that since it's static and the threads are cached for 60 seconds, only the first test will actually spawn a new thread in the pool, while subsequent tests reuse that thread.

缓存线程池似乎最适合我。问题在于,由于它是静态的并且线程被缓存了 60 秒,因此只有第一个测试才会在池中实际产生一个新线程,而后续测试会重用该线程。

Unit test code:

单元测试代码:

public void testDoCallExecutesTaskInAnotherThread() {    
    final Client client = this.createClient();
    final ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) client.getExecutorService(); // gets the static thread pool
    final int initPoolSize = threadPoolExecutor.getPoolSize();
    final Response response = client.doCall();
    Assert.assertEquals(initPoolSize + 1, threadPoolExecutor.getPoolSize());
}

Advice on how to get this working, or another approach altogether would be appreciated.

关于如何使这项工作或完全采用另一种方法的建议将不胜感激。

回答by mhaller

Mock the ThreadFactory:

嘲笑ThreadFactory

  ThreadFactory mock = new CustomObservableThreadFactory();
  ExecutorService executorService = Executors.newCachedThreadPool(mock);
  1. Inject the ExecutorService into the class under test as usual
  2. But use a custom ThreadFactoryfor creating the cached ThreadPool: The ThreadFactory will be called whenever a new Thread is to be called. You can then trace these instantiations as you like, e.g.with a listener or counter.
  1. 像往常一样将 ExecutorService 注入到被测类中
  2. 但是使用自定义 ThreadFactory来创建缓存的 ThreadPool:每当要调用新线程时,都会调用 ThreadFactory。然后,您可以随心所欲地跟踪这些实例,例如使用侦听器或计数器。