CDI in JUnit tests with Jersey Test Framework

2k Views Asked by At

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?

1

There are 1 best solutions below

2
fxrobin On BEST ANSWER

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 :

  • the @EnableWeld placed on the JUnit test class.
  • the @WeldSetup placed on a WeldInitiator field, to lookup to all annotated classes.
  • don't forget beans.xml in META-INF of your test classpath in order to setup the discovery-mode.
  • @Slf4j is a lombok annotation, you don't need it (unless you are already using Lombok)

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.