Isolated unit testing of Java EE and Spring components

When developing modern Spring or Jakarta EE based applications and micro services there is a need for fine-granular component testing. I.e. you do not want to test your code in a full-blown environment only, because such tests will be slow.

Instead, you might want to write tests at the component level using a mixture of mocked dependencies and real assets like the (in-memory) database.

needle4k is a Kotlin-based relaunch and upgrade of the well-known needle4j framework. It may be used with any JVM-based language and allows to develop modular tests with minimal effort.

Core features

  • Automated setup of components annotated with @ObjectUnderTest
  • Constructor, method and field based dependency injection
  • Configurable injection of mock or real objects
  • Extensible by providing custom injection providers
  • Database testing using Hibernate
  • Optionally clear or setup database before/after each test
  • Automatic injection of EntityManager, EntityManagerFactory, EntityTransaction, and DataSource
  • As well Java EE as Jakarta EE are supported
  • Transaction and reflection utilities
  • needle4k can be used with JUnit4, JUnit5 or TestNG.
  • Pluggable Mock providers: EasyMock and Mockito in particular

Writing your first test

Given a simple User DAO:

@Stateless
@LocalBean
public class UserDao
{
  @PersistenceContext
  private EntityManager entityManager;

  @EJB
  private MetricsService metricsService;

  public List<User> findByName(final String name)
  {
    metricsService.measureDuration(...);

    return entityManager.createNamedQuery(FIND_BY_STREET)
       .setParameter("name", name).getResultList();
  }
}

You can write a simple test:

@ExtendWith(JPANeedleExtension.class) // JUnit5 extension mechanism used
public class UserDaoTest {
  // Mock object will be created and injected automatically everywhere
  @InjectIntoMany 
  private MetricsService metricsService;

  // Inject components directly into test using standard annotations
  @Inject
  private EntityManager entityManager;

  // Create tested component and inject dependencies into it
  // and its dependent objects
  @ObjectUnderTest
  private UserDao userDao;

  @Test
  public void testFindByUsername() {
    final User user = new User("demo");
    entityManager.persist(user);
        
    User userFromDb = userDao.findByName("demo");
    assertThat(userFromDb).isEqualTo(user);
  }
}

For more information please consult the needle4k homepage and take a look at the quick start project.

Posted in All