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
}