0

I'm trying to run integrations tests on my project, using Arquillian. I'm using:

  • Java 11
  • Jakarta EE 9
  • OpenLiberty 21.0.0.4-beta (for the Jakarta EE 9 support)
  • JUnit 5
  • Arquillian

I can test my controllers by making API calls, including the ones that adjust my database. My problem lies in controller which data is in my database at one point, as I can't get an EntityManager in my test class, in any way I've tried:

  • @PersistenceUnit(name = "default")
    private EntityManagerFactory entityManagerFactory;
    
  • @PersistenceContext(name = "default")
    private EntityManager entityManager;
    
  • EntityManagerFactory factory = Persistence.createEntityManagerFactory("default");  
    EntityManager manager = factory.createEntityManager();
    

None of them work, either returning null or throwing an error: jakarta.persistence.PersistenceException: No Persistence provider for EntityManager named default. I'm providing data to the Derby database using a sql-script, but that only works on startup and not during the tests itself.

I'm sure my persistence is working as otherwise my tests itself would fail, as they use EntityManager too.

Extra information as requested

arquillian

<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/schema/arquillian"
            xsi:schemaLocation="http://jboss.org/schema/arquillian
    http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
    <defaultProtocol type="Servlet 5.0"/>

    <engine>
        <property name="deploymentExportPath">target/</property>
    </engine>

    <container qualifier="liberty-remote" default="true">
        <configuration>
            <property name="hostName">localhost</property>
            <property name="serverName">testing</property>
            <property name="username">admin</property>
            <property name="password">admin</property>
            <property name="httpPort">9080</property>
            <property name="httpsPort">9500</property>
            <property name="serverStartTimeout">120</property>
            <property name="appDeployTimeout">120</property>
        </configuration>
    </container>
</arquillian>

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>redacted</groupId>
    <artifactId>redacted</artifactId>
    <version>1.0</version>
    <name>redacted</name>
    <packaging>war</packaging>

    <properties>
        <!-- Global Maven settings -->
        <java.version>11</java.version>
        <jakartaee.version>9.0.0</jakartaee.version>
        <hibernate.version>5.4.29.Final</hibernate.version>
        <nimbuds.version>9.7</nimbuds.version>
        <bcrypt.version>0.4.3</bcrypt.version>
        <modelmapper.version>2.3.9</modelmapper.version>

        <junit.version>5.7.1</junit.version>
        <arquillian.version>1.7.0.Alpha9</arquillian.version>
        <assertj.version>3.19.0</assertj.version>
        <mockito.version>3.8.0</mockito.version>

        <jersey.version>3.0.1</jersey.version>
        <arquillian-liberty-jakarta.version>2.0.0-M1</arquillian-liberty-jakarta.version>
        <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
        <maven-war-plugin.version>3.3.1</maven-war-plugin.version>
        <maven-failsafe-plugin.version>3.0.0-M5</maven-failsafe-plugin.version>
        <maven-surefire-report-plugin.version>3.0.0-M5</maven-surefire-report-plugin.version>
        <liberty.runtime.version>21.0.0.4-beta</liberty.runtime.version>
        <!-- WARNING: 10.15.x.x does not work with openliberty 20.0.0.1 -->
        <!-- <derby.version>10.14.2.0</derby.version>-->
        <liberty-maven-plugin.version>3.3.4</liberty-maven-plugin.version>
        <cxf.version>3.3.5</cxf.version>
        <jpa-unit.version>0.5.0</jpa-unit.version>

        <maven.compiler.release>${java.version}</maven.compiler.release>
    </properties>

    <dependencies>
        <!-- Jakarta EE -->
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>${jakartaee.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- JWT -->
        <dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
            <version>${nimbuds.version}</version>
        </dependency>

        <!-- BCrypt -->
        <dependency>
            <groupId>de.svenkubiak</groupId>
            <artifactId>jBCrypt</artifactId>
            <version>${bcrypt.version}</version>
        </dependency>

        <!-- Model Mapper -->
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>${modelmapper.version}</version>
        </dependency>

        <!-- Testing -->
        <dependency>
            <groupId>org.jboss.arquillian.junit5</groupId>
            <artifactId>arquillian-junit5-container</artifactId>
            <version>${arquillian.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.protocol</groupId>
            <artifactId>arquillian-protocol-servlet-jakarta</artifactId>
            <version>${arquillian.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>${assertj.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.openliberty.arquillian</groupId>
            <artifactId>arquillian-liberty-remote-jakarta</artifactId>
            <version>${arquillian-liberty-jakarta.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-binding</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-client</artifactId>
            <version>${jersey.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>${mockito.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>${mockito.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>${maven-war-plugin.version}</version>
                <configuration>
                    <packagingExcludes>pom.xml</packagingExcludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven-failsafe-plugin.version}</version>
                <executions>
                    <execution>
                        <id>integration-test</id>
                        <goals>
                            <goal>integration-test</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>verify</id>
                        <goals>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <systemPropertyVariables>
                        <arquillian.launch>liberty-remote</arquillian.launch>
                        <java.util.logging.config.file>
                            ${project.build.testOutputDirectory}/logging.properties
                        </java.util.logging.config.file>
                    </systemPropertyVariables>
                </configuration>
            </plugin>
            <plugin>
                <groupId>io.openliberty.tools</groupId>
                <artifactId>liberty-maven-plugin</artifactId>
                <version>${liberty-maven-plugin.version}</version>
                <configuration>
                    <arquillianProperties>
                        <javaVmArguments>
                            -Dsystem.context.root=/${project.artifactId}
                        </javaVmArguments>
                    </arquillianProperties>
                    <installDirectory>C:\Users\KDECC76\wlp</installDirectory>
                    <serverName>someserver</serverName>
                    <verifyTimeout>90</verifyTimeout>
                    <serverStartTimeout>120</serverStartTimeout>
                </configuration>
            </plugin>
        </plugins>
        <testResources>
            <testResource>
                <directory>src/test/resources</directory>
                <includes>
                    <include>*</include>
                </includes>
                <excludes>
                    <exclude>server.xml</exclude>
                </excludes>
            </testResource>
        </testResources>
    </build>
</project>
//  ... redacted

import jakarta.persistence.*;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit5.ArquillianExtension;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith({ArquillianExtension.class})
class CertificateControllerIT extends IntegrationTest {

    @ArquillianResource
    private URL base;
    private Client client;
    @PersistenceUnit(name = "default")
    private EntityManagerFactory entityManagerFactory;
    @PersistenceContext(name = "default")
    private EntityManager entityManager;

    @Deployment(testable = false)
    public static WebArchive createDeployment() {
        return IntegrationTest.createDeployment()
                .addClasses(CertificateRepository.class, CertificateService.class, CertificateController.class)
                .addClasses(CertificateCreateDTO.class, CertificateReadDTO.class, CertificateDeleteDTO.class);
    }

    @BeforeEach
    void setup() {
        this.client = ClientBuilder.newClient();
    }

    @AfterEach
    void teardown() {
        if (this.client != null)
            this.client.close();
    }
    
    @Test
    void manager() {
        assertThat(entityManager).isNotNull();
    }

    @Test
    void factory1() {
        assertThat(entityManagerFactory).isNotNull();
    }

    @Test
    void factory2() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("default");
        assertThat(factory).isNotNull();

        EntityManager manager = factory.createEntityManager();
        assertThat(manager).isNotNull();
    }

    //  ... redacted

    @Test
    void createCertificateAdminDuplicate() throws MalformedURLException {
        // FIXME - Seed database.
        final CertificateCreateDTO certificate = new CertificateCreateDTO("Oracle Certified Professional, Java SE 7 Programmer");

        final WebTarget target = this.client.target(new URL(this.base, "api/certificates").toExternalForm());
        try (final Response response = target.request()
                .header(HttpHeaders.AUTHORIZATION, createToken(Authority.ADMIN))
                .post(Entity.entity(certificate, MediaType.APPLICATION_JSON_TYPE))) {
            assertThat(response.getStatus()).isEqualTo(Status.CONFLICT.getStatusCode());

            SimpleExceptionMessage entity = response.readEntity(SimpleExceptionMessage.class);
            assertThat(entity).isNotNull();
            assertThat(entity.getMessage()).isEqualTo("Name is already in use.");
        }
    }
    
    //  ... redacted

}

The 3 persistence tests fail, while the api test works.

The controller that I'm testing:

//  ... redacted
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

@ApplicationScoped
@Path("certificates")
public class CertificateController extends BaseController {

    @Inject
    private CertificateService certificateService;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    @RolesAllowed(Authority.ADMIN)
    public Response createCertificate(CertificateCreateDTO dto) {
        return certificateService.createCertificate(dto);
    }

}
//  ... redacted
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.PersistenceException;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import org.modelmapper.ModelMapper;
import org.modelmapper.TypeToken;

import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

@ApplicationScoped
public class CertificateService {

    private static final Logger LOGGER = Logger.getLogger(CertificateService.class.getName());

    protected static final int CERTIFICATES_SIZE = 20;
    private static final ModelMapper MAPPER = new ModelMapper();

    @Inject
    private CertificateRepository repository;

    //  ... redacted

    public Response createCertificate(CertificateCreateDTO dto) {
        Certificate newCertificate = MAPPER.map(dto, Certificate.class);

        try {
            repository.save(newCertificate);
        } catch (Exception exception) {
            if (exception.getCause() instanceof PersistenceException && exception.getCause().getMessage() != null &&
                    (exception.getCause().getMessage().contains("Duplicate entry") || exception.getCause().getMessage().contains("duplicate key value"))) {
                return Response.status(Status.CONFLICT.getStatusCode(), "Name is already in use.")
                        .entity(new SimpleExceptionMessage("Name is already in use.")).build();
            }
            exception.printStackTrace();
            return Response.status(Status.INTERNAL_SERVER_ERROR).build();
        }

        return Response.ok(newCertificate).build();
    }

    //  ... redacted

}
//  ... redacted
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.transaction.Transactional;

import java.util.List;

@Transactional
@ApplicationScoped
public class CertificateRepository extends GenericRepository<Certificate> {

    @PersistenceContext(name = "default")
    protected EntityManager entityManager;

    public void save(Certificate entity) {
        entityManager.persist(entity);
    }
    
    //  ... redacted
    
}
  • Try this `new PersistenceProvider().createEntityManagerFactory` – Med Elgarnaoui Apr 06 '21 at 16:28
  • Depending how you run your tests, the persistence.xml location might be different and it is not being found during your tests. – Gas Apr 07 '21 at 10:40
  • @Gas I've tried a lot of different locations. It currently is in `WEB-INF/classes/META-INF`, and it seems to work as I can properly test my api, which relies on data that I provide using a `data.sql` script. @MedElgarnaoui `PersistenceProvider` is an abstract class, so I can't instantiate it. – DeKleineKobini Apr 07 '21 at 17:45
  • 1
    You need to add `pom.xml` and your test class, as it is hard to tell how you run the test. Is it unit test, is it in arquillian, etc... WEB-INF is correct location if you run in the container but if you just have unit test it should be straight META-INF. Also your provider might not be found during tests - check this - https://stackoverflow.com/questions/44999884/junit-eclipse-jpa-persistence-xml-not-located – Gas Apr 08 '21 at 09:23
  • @Gas I did state that I'm running them though Arquillian in my original post. The strange thing is that my persistence does work, as that's how my API works, even during tests. I've added more information in my question. – DeKleineKobini Apr 08 '21 at 11:13
  • I'm assuming that by 3 failing tests you are mentioning `manager,factory1, factory2`? There is a major difference, as the API test is using EM from the server side (configured by deployed app) and these 3 just include EM in the 'client' side. So that's why it is not visible. Check this thread for some hints - https://stackoverflow.com/questions/30890887/unable-to-inject-entitymanager-in-jpa-integration-testing-with-arquillian-and-wi – Gas Apr 08 '21 at 14:54
  • @Gas Thank you very much. That explains why it has not been working. – DeKleineKobini Apr 09 '21 at 08:00
  • I encountered the same issue when upgrading to Jakarta EE 10, https://github.com/OpenLiberty/liberty-arquillian/issues/134 But in the original Jakarta EE 8 it worked well. https://github.com/hantsy/jakartaee8-starter-boilerplate/blob/master/src/test/java/com/example/it/OrderDaoTest.java – Hantsy Jun 12 '23 at 01:19

0 Answers0