Java 如何测试实现线程的代码?

Java 如何测试实现线程的代码?,java,junit,mocking,mockito,Java,Junit,Mocking,Mockito,我希望能够junit测试以下内容: private ExecutorService executor = Executors.newSingleThreadExecutor(); public void foo() { final EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory(); executor.execute(new Runnable() {

我希望能够junit测试以下内容:

private ExecutorService executor = Executors.newSingleThreadExecutor();

public void foo() {

  final EntityManagerFactory entityManagerFactory =
      entityManager.getEntityManagerFactory();

  executor.execute(new Runnable() {
    @Override
    public void run() {
      EntityManager entityManager =
          entityManagerFactory.createEntityManager();
      Session session = (Session) entityManager.getDelegate();
      try {
        SQLQuery query =
            session.createSQLQuery("SELECT * from foo_function()");

      } catch (HibernateException exception) {
        LOGGER.error("Exception: " + exception);
      }
    }
  });
}
我用的是Mockito。我试图让它抛出一个异常,例如:

Mockito.doThrow(SQLException.class).when(mockSession).createSQLQuery(any(String.class));

它将在生成的线程中引发异常,但当我将其作为Junit测试运行时,它不会失败。

您需要替换被测类中的Executor或ExecutorService:

public class YourClass {
  private Executor executorService = Executor.newSingleThreadExecutor();
  public YourClass() {}

  /** package-visible for testing */
  YourClass(Executor executor) {
    /* ... */
  }

  public void foo() { /* ... */ }
}
…或者只是在您正在测试的方法中:

public class YourClass {
  public void foo() {
    foo(executorService);
  }

  /** package-visible for testing */
  void foo(Executor executor) {
    /* ... */
  }
}
之后,您可以使用手动或基于番石榴的直接执行器,如中所示:

或者将其替换为Mockito mock,以便在Runnable运行之前和之后进行测试:

@Test public void fooShouldHandlException() {
  Executor mockExecutor = Mockito.mock(Executor.class);
  ArgumentCaptor<Runnable> runnableCaptor =
      ArgumentCaptor.forClass(Runnable.class);
  systemUnderTest.foo(mockExecutor);
  // assert "before Runnable is run" state, if applicable
  verify(mockExecutor).execute(runnableCaptor.capture());
  runnableCaptor.getValue().run();
  // assert "after Runnable is run" state
}

调试线程入口过程时,会话对象确实是mockito mock对象吗?是的,会话是mock的。whenmockEntityManager.getDelegate.thenReturnmockSession;你到底想测试什么?我不明白这句话:它会在生成的线程中抛出异常,但当我将其作为Junit测试运行时,它不会失败。我猜我要做什么,如何捕获executor服务生成的线程中抛出的异常?
@Test public void fooShouldHandlException() {
  Executor mockExecutor = Mockito.mock(Executor.class);
  ArgumentCaptor<Runnable> runnableCaptor =
      ArgumentCaptor.forClass(Runnable.class);
  systemUnderTest.foo(mockExecutor);
  // assert "before Runnable is run" state, if applicable
  verify(mockExecutor).execute(runnableCaptor.capture());
  runnableCaptor.getValue().run();
  // assert "after Runnable is run" state
}