在单元测试中从Runnable捕获Java异常

问题描述 投票:1回答:1

我有下面的代码

public final class JoinableTaskPool<T> extends ABC {
       private int taskCounter;
       private final Object monitor;
       private final ExtendedThreadPoolExecutor service;
       private final CompletionService<T> compService;

       public Future<T> submit(final Callable<T> task) {
           final Future<T> result = compService.submit(task);
           service.submit(new Runnable() {
             public void run() {
                try {
                    final Future<T> result = compService.take();
                    try {
                        handler.processResult(result);
                    } catch (final Throwable t) {
                        throw new SearchException("Task has an error", t);
                    }
                } catch (InterruptedException e) {
                    throw new SearchException("Task has an error", e);
                }
            }
          } 
          return result;
       }

  public void join() {
    synchronized (monitor) {
        while (taskCounter != 0) {
            try {
                monitor.wait();
            } catch (InterruptedException e) {
                error(e, "Interrupted in join");
            }
        }
  }
  }

ExtendedThreadPoolExecutor类的定义如下

public class ExtendedThreadPoolExecutor extends ThreadPoolExecutor {

    public ExtendedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if(t != null) {
            throw new SearchException("Error while executing the task", t);
        }
    }
}

我正在尝试为此方法编写单元测试。下面是方法

@RunWith(MockitoJUnitRunner.class)
public class TestJoinableTaskPool<T> {

    private JoinableTaskPool<T> pool;

    @Before
    public void setUp() {
        pool = new JoinableTaskPool<T>(1);
    }

    @After
    public void tearDown() {
        pool.shutdown();
    }

    @Test (expected = SearchException.class)
    public void testSubmit() throws Exception{
        Callable task = (Callable<T>) () -> null;

        Mockito.when(pool.getFinishHandler().processResult(result))
                .thenThrow(RuntimeException.class);

        pool.submit(task);
    }
}

由于SearchException异常以可运行方式抛出,因此无法在Submit方法之外访问它。如果我要返回executorService.submit返回的Future,则可以执行future.get()来获取异常,但是我要返回另一个Future(result变量)。因此,在编写单元测试时,我无法抛出异常。

此外,为了覆盖单元测试中的异常,我也重写了afterExecute(),但找不到找到它的方法。

我如何测试从单元测试的可运行项抛出的异常。任何帮助,将不胜感激。

java unit-testing exception future runnable
1个回答
0
投票

撇开他的代码闻到一英里以外,您可以做的是创建其他接口,例如

public interface MyErrorHandler { handleError(Exception e)

在执行程序池中实现它,并在异常时调用它。然后,您可以使用Mockito.spy来查看是否已在MyErrorHandler上调用tha方法(cglib应该允许您执行此操作,即使没有额外的界面也是如此。)

或者,您可以定义MyExceptionHandler实例应该传递给执行者(通过构造函数或setter方法,以便您能够提供此类回调的依赖于用例的实现]

© www.soinside.com 2019 - 2024. All rights reserved.