EntityManager 在我的测试类中为空,但在我的服务中工作

问题描述

我正在尝试使用 Arquillian 在我的项目上运行集成测试。我正在使用:

  • Java 11
  • 雅加达 EE 9
  • OpenLiberty 21.0.0.4-beta(用于 Jakarta EE 9 支持
  • JUnit 5
  • 阿奎利安

我可以通过调用 API 来测试我的控制器,包括调整我的数据库的那些。我的问题在于控制器有哪些数据在我的数据库中,因为我无法以我尝试过的任何方式在我的测试类中获得 EntityManager:

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

它们都不起作用,要么返回 null 要么抛出错误jakarta.persistence.PersistenceException: No Persistence provider for EntityManager named default。 我正在使用 sql 脚本向 Derby 数据库提供数据,但这仅在启动时有效,而在测试本身期间无效。

我确信我的持久性是有效的,否则我的测试本身就会失败,因为它们也使用 EntityManager。

根据要求提供额外信息

阿奎利安

<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

}

3 个持久性测试失败,而 api 测试有效。

我正在测试的控制器:

//  ... 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
    
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)