0

I want to be able to junit test the following:

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);
      }
    }
  });
}

I am using Mockito. I tried to get it to throw an exception, for example:

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

It would throw an exception in the spawned thread, but it doesn't fail when I run it as a Junit test.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
PhoonOne
  • 2,678
  • 12
  • 48
  • 76
  • When you debug your thread "entry procedure", is indeed the session object is a mockito mock object ? – Shmil The Cat Dec 09 '14 at 14:48
  • Yup, session is mocked. when(mockEntityManager.getDelegate()).thenReturn(mockSession); – PhoonOne Dec 09 '14 at 14:53
  • 1
    What are you trying to test, exactly? I don't understand this sentence: "*It would throw an exception in the spawned thread, but it doesn't fail when I run it as a Junit test.*". – Duncan Jones Dec 09 '14 at 14:55
  • I guess what im trying to do it, how to catch the exception thrown in the thread spawned by the executor service? – PhoonOne Dec 09 '14 at 15:56

1 Answers1

0

You'll want to replace the Executor or ExecutorService, either in the class under test:

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

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

  public void foo() { /* ... */ }
}

...or just in the method you're testing:

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

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

After that, you can either use a manual or Guava-based direct executor, as in this SO question and its answers:

@Test public void fooShouldHandlException() {
  // ...
  systemUnderTest.foo(new Executor() {
    @Override public void execute(Runnable r) { r.run(); }
  });
  // ...
}

Or replace it with a Mockito mock to test both before and after the Runnable is run:

@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
}
Community
  • 1
  • 1
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251