Testing Hibernate 7: Mocking JNDI DataSources Without the Container
Testing enterprise applications can be a nightmare when your code relies on a JNDI (Java Naming and Directory Interface) DataSource. You shouldn't need a full-blown JBoss or WildFly server just to run a single unit test. If you are upgrading to Hibernate 7, you might notice that the way we handle container-managed resources has evolved. In this guide, we will explore how to mock an in-memory JNDI DataSource so your tests remain fast, isolated, and reliable without the overhead of an application server. The Problem: The "NamingException" Wall You’ve written a perfect Data Access Object (DAO) or Service layer. It works beautifully in production because the application server (like GlassFish, Payara, or WildFly) provides the JNDI lookup. However, the moment you run a JUnit 5 test in your IDE, you hit the dreaded javax.naming.NoInitialContextException or NamingException. The environment outside the container doesn't have a JNDI provider. The InitialContext is empty, and Hibernate fails to boot because it cannot find the resource it needs. You’re stuck between two bad choices: either skip database testing entirely or install a heavy container locally. The Agitation: Why "Real" JNDI is a Testing Antipattern Relying on a real JNDI provider for local development or CI/CD pipelines creates several bottlenecks: Feedback Loop Latency: Starting an application server adds minutes to your build time. For a developer, a 10-second test suite is a productivity booster; a 10-minute suite is a distraction. Environmental Drift: If the server configuration changes in the dev environment but not in the test environment, your tests break—not because of your code, but because of the infrastructure. The Jakarta EE 10/11 Shift: Hibernate 7 introduces tighter integration with Jakarta EE 10 and 11. Older mocking hacks—like manually overriding the InitialContextFactory with custom inner classes—often fail due to stricter class-loading mechanisms and the updated jakarta.resource and jakarta.transaction APIs. The Solution: Simple-JNDI and Hibernate 7 The most robust way to solve this is by using Simple-JNDI, a library that provides a file-based or memory-based JNDI implementation specifically designed for testing environments. By combining this with the H2 database, we can simulate a production-grade DataSource in milliseconds.