michael
michael

Reputation: 397

Unit test for throwing RejectedExecutionException by Java thread pool

I am new to using Java thread pool. Now i have a use case for unit test when a new task comes and current thread number is max number and queue is full. I know in this case RejectedExecutionException will be thrown. But how to best produce this scenario, what i can think of now is something like this:

LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(1);
ExecutorService ex = new ThreadPoolExecutor(2, 2, 60L, TimeUnit.MILLISECONDS, queue);
int rejected = 0;
try{
    while (true){
        ex.submit(() -> {
            System.out.println("Queue remaining size: " + queue.remainingCapacity());
            System.out.println("Thread amount in pool: " + ((ThreadPoolExecutor)ex).getPoolSize() + "\n");
        });
    }
}
catch (RejectedExecutionException e){
    System.out.println(++rejected);
}

This is basic idea and i need to convert this using EasyMock if it is right way. I wonder if there is better way if using EasyMock instead of keep submitting task until thread and queue is full.

Upvotes: 2

Views: 1908

Answers (4)

Timothy Truckle
Timothy Truckle

Reputation: 15622

You might move the execution code to a new class where you can easily mock out the dependencies:

class MyExecuter extends Executer{
  private final ExecuterService executerService;
  private final PrintStream out;
  MyExecuter(ExecutorService executerService, PrintStream out){
    this.executerService  =  executerService;
    this.out  =  out;
  }
  @override 
   public void execute(Runnable r) {
     int rejected = 0;
     try{
        while (true)
        {
            executerService.submit(() -> {
               // do your business logic which usually does not care about the executor or the queue...
            });
        }
    }
    catch (RejectedExecutionException e)
    {
        out.println(++rejected);
    }

   }
}

Your code would change to this:

LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(1);
ExecutorService ex = new ThreadPoolExecutor(2, 2, 60L, TimeUnit.MILLISECONDS, queue);
Executor mex = new MyExcecutor(ex, System.out);
mex.execute();

Now you can create a Test for MyExcecutor that gets mocks for ExecutorService and PrintStream so that you can verify interaction with them.

Upvotes: 0

Gray
Gray

Reputation: 116908

This is basic idea and i need to convert this using EasyMock if it is right way. I wonder if there is better way if using EasyMock instead of keep submitting task until thread and queue is full.

Anything that EasyMock would do would most likely take more code than your anonymous Runnable. You could certainly do it but you would use an IAnswer object instead of the Runnable so I'm not sure it's much better.

The real question is what are you testing? Are you really making sure that the ThreadPoolExecutor is doing it's job or are you really trying to mock out an ExecutorService or as @Warren mentioned a ThreadPoolExecutor.

I'd do a Thread.sleep(1000) in your Runnable and submit 4 of them instead of the while loop. You can also create one object at the start and submit it multiple times. Please excuse the Java 7 code:

BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(1);
ExecutorService ex = new ThreadPoolExecutor(2, 2, 60L, TimeUnit.MILLISECONDS, queue);
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
    }
};
try {
    ex.submit(runnable); // 1st thread
    ex.submit(runnable); // 2nd thread
    ex.submit(runnable); // 1st queued
    ex.submit(runnable); // rejected
} catch (RejectedExecutionException e) {
    System.out.println("rejected");
}

Upvotes: 1

Ravindra babu
Ravindra babu

Reputation: 38940

One simple solution:

Call shutdown before submitting the task.

If you call submit() after shutdown(), you will get this type of execption:

java.util.concurrent.RejectedExecutionException: Task MyRunnable@3dcc0a0f
rejected from java.util.concurrent.ThreadPoolExecutor

Upvotes: 0

Warren Dew
Warren Dew

Reputation: 8938

I'm not familiar with EasyMock in particular, but the general approach should be to mock out the ThreadPoolExecutor.

Upvotes: 1

Related Questions