dependency-injectionjerseycdiinjectjersey-test-framework

CDI in JUnit tests with Jersey Test Framework


We are using the Jersey Test Frameworks for API testing. In test-mode, we use an h2 database, mysql in production. Everything is fine to this point.

Now i want to write tests for our repositories to check if the data is written properly to the database.

I can't inject any classes in my tests so i am using the standard constructor the create an new instance of RepositoryA. Works for me.

Now the problem: RepositoryA is now injecting an instance of RepositoryB. And injection isn't working on test-scope.

Is it possible to get injection running in this environment?


Solution

  • Depending on the versions of the libraries you are using, running CDI in JUnit Test is different.

    First you need to add this dependency, selecting the right version :

    <dependency>
       <groupId>org.jboss.weld</groupId>
       <artifactId>weld-junit5</artifactId> // or weld-junit4
       <version>1.3.0.Final</version>
       <scope>test</scope>
    </dependency>
    

    Then you can enable Weld in your JUnit test. Here is an example of injecting a repository for an entity class called VideoGame :

    @Slf4j
    @EnableWeld
    class VideoGameRepositoryTest
    {
        @WeldSetup 
        private WeldInitiator weld = WeldInitiator.performDefaultDiscovery();
    
        @Inject
        private VideoGameRepository repo;
    
        @Test
        void test()
        {
            VideoGame videoGame = VideoGameFactory.newInstance();
            videoGame.setName("XENON");
            repo.save(videoGame);
            // testing if the ID field had been generated by the JPA Provider.
            Assert.assertNotNull(videoGame.getVersion());
            Assert.assertTrue(videoGame.getVersion() > 0);
           log.info("Video Game : {}", videoGame);
        }
     }
    

    The important parts are :

    Here the VideoGameRepository instance benefits injection as well, like in a classical CDI project.

    Here is the code of the VideoGameFactory which gets a brand new instance of the entity class marked with @Dependent scope. This factory programmatically invokes the CDI current context.

    public class VideoGameFactory
    {
        public static VideoGame newInstance()
        {
            // ask CDI for the instance, injecting required dependencies.
            return CDI.current().select(VideoGame.class).get();
        }
    }
    

    Alternately, you can have a look to Arquillian which can come with a full Java EE server in order to have all the needed dependencies.