Тестовые репозитории DeltaSpike не могут внедрить EntityManager - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь запустить простой тест для репозитория DeltaSpike.Однако я не могу ввести Entity Manager.Я использую производителя, который находится, и источники тестирования:

@ApplicationScoped
public class EntityManagerProducer {

    @Produces
    public EntityManager getEntityManager() {
        return Persistence
          .createEntityManagerFactory("primary-test")
          .createEntityManager();
    }
}

В папке META-INF в ресурсах теста у меня есть файл persistence.xml с определенной единицей сохранения основного теста:

<persistence version="2.0"
         xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="primary-test" transaction-type="RESOURCE_LOCAL">
        <properties>
            <!-- Configuring JDBC properties -->
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>

            <!-- Hibernate properties -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
            <property name="hibernate.format_sql" value="false"/>
            <property name="hibernate.show_sql" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

В очень простом модуле я пытаюсь ввести Entity Manager:

@RunWith(CdiTestRunner.class)
public class UserRepositoryTest {

    @Inject
    private EntityManager entityManager;

    @Test
    public void shouldReturnEmptyListWhenDBIsEmpty() {
        // dummy test here
    }
}

Однако, когда я запускаю его, я получаю исключение:

 WELD-001408 Unsatisfied dependencies for type [EntityManager] with qualifiers [@Default] at injection point [[field] @Inject private com.repository.UserRepositoryTest.entityManager]

Мой pom.xml имеетзависимости от Apache DeltaSpike Test Module и Weld:

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <deltaspike.version>1.8.2</deltaspike.version>
  <weld.version>1.1.10.Final</weld.version>
</properties>

<dependency>
  <groupId>org.apache.deltaspike.modules</groupId>
  <artifactId>deltaspike-test-control-module-api</artifactId>
  <version>${deltaspike.version}</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.apache.deltaspike.modules</groupId>
  <artifactId>deltaspike-test-control-module-impl</artifactId>
  <version>${deltaspike.version}</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.apache.deltaspike.cdictrl</groupId>
  <artifactId>deltaspike-cdictrl-weld</artifactId>
  <version>${deltaspike.version}</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>org.jboss.weld.se</groupId>
  <artifactId>weld-se-core</artifactId>
  <version>${weld.version}</version>
  <scope>test</scope>
</dependency>

Есть идеи, почему Entity Manager нельзя вводить?Я не хочу использовать Arquillian.

РЕДАКТИРОВАТЬ: Текущий pom.xml:

<groupId>com.us</groupId>
<artifactId>deltaspike-samples</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>DeltaSpike samples</name>

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <deltaspike.version>1.8.1</deltaspike.version>
  <weld.version>3.0.4.Final</weld.version>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.deltaspike.distribution</groupId>
      <artifactId>distributions-bom</artifactId>
      <version>${deltaspike.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>org.wildfly.bom</groupId>
      <artifactId>jboss-javaee-7.0-with-hibernate</artifactId>
      <version>8.2.2.Final</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.core</groupId>
    <artifactId>deltaspike-core-api</artifactId>
    <scope>compile</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.core</groupId>
    <artifactId>deltaspike-core-impl</artifactId>
    <scope>runtime</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-data-module-api</artifactId>
    <scope>compile</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-data-module-impl</artifactId>
    <scope>runtime</scope>
  </dependency>

  <!--Test dependencies-->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-test-control-module-api</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-test-control-module-impl</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-api</artifactId>
    <version>${deltaspike.version}</version>
    <scope>compile</scope>
  </dependency>

  <dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-weld</artifactId>
    <version>${deltaspike.version}</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>2.0</version>
  </dependency>

  <dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-shaded</artifactId>
    <version>3.0.4.Final</version>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.1-api</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.jboss.spec.javax.annotation</groupId>
    <artifactId>jboss-annotations-api_1.2_spec</artifactId>
    <scope>test</scope>
  </dependency>

</dependencies>

Ответы [ 2 ]

0 голосов
/ 28 ноября 2018

У меня были похожие проблемы с Deltaspike и интеграционным тестом Junit5 хранилища базы данных.По сути, я не смог внедрить хранилище при использовании аннотаций Junit5 @Test.Мне пришлось использовать аннотации Junit4 @Test в качестве обходного пути.

0 голосов
/ 05 июня 2018

Использование CDI в JAVA SE требует, чтобы beans.xml был введен в META-INF, хотя это необязательно с Java EE 7.

Затем установите режим обнаружения на annotated, и ваш производитель должен быть обнаружен.

Вот рабочая конфигурация:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <deltaspike.version>1.8.2</deltaspike.version>
    <weld.version>3.0.4.Final</weld.version>
</properties>

Теперь, вот как вы настраиваете базовую зависимость DeltaSpike:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.deltaspike.distribution</groupId>
            <artifactId>distributions-bom</artifactId>
            <version>${deltaspike.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

В зависимостях вы должны иметьtheses specs:

<dependency>
    <groupId>javax.enterprise</groupId>
    <artifactId>cdi-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>javax.transaction</groupId>
    <artifactId>javax.transaction-api</artifactId>
    <version>1.3</version>
</dependency>   

<dependency>
    <groupId>javax.persistence</groupId>
    <artifactId>javax.persistence-api</artifactId>
    <version>2.2</version>
</dependency>

Теперь пришло время зависеть от реализаций.

Сначала сам Deltaspike:

<dependency>
    <groupId>org.apache.deltaspike.core</groupId>
    <artifactId>deltaspike-core-api</artifactId>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.core</groupId>
    <artifactId>deltaspike-core-impl</artifactId>
    <scope>runtime</scope>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-api</artifactId>
    <scope>compile</scope>
</dependency>

Затем JBoss Weld 3 (CDI 2.0 impl)

<dependency>
    <groupId>org.jboss.weld.se</groupId>
    <artifactId>weld-se-shaded</artifactId>
    <version>${weld.version}</version>
    <scope>runtime</scope>
</dependency>

и контроллер сварки для DeltaSpike:

<dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-weld</artifactId>
    <scope>runtime</scope>
</dependency>

Затем модуль данных DeltaSpike:

<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-data-module-api</artifactId>
    <version>${deltaspike.version}</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-data-module-impl</artifactId>
    <version>${deltaspike.version}</version>
    <scope>runtime</scope>
</dependency>

Теперь пришло время для реализации JPA (EclipseLink JPA 2.7.1) и встроенный сервер базы данных H2:

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.jpa</artifactId>
    <version>2.7.1</version>
</dependency>

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.197</version>
    <scope>runtime</scope>
</dependency>

Чтобы создать модульный тест с JUnit 5, вам потребуется:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.1.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.1.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.1.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.1.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-runner</artifactId>
    <version>1.1.0</version>
    <scope>test</scope>
</dependency>

И чтобы иметь возможность запускать CDI с одной аннотациейв классе JUnit это также необходимо:

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

Чтобы включить JUnit 5 в Маven, вы должны настроить maven-surefire-plugin:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19.1</version>
            <dependencies>
                <dependency>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>junit-platform-surefire-provider</artifactId>
                    <version>1.0.3</version>
                </dependency>
                <dependency>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-engine</artifactId>
                    <version>5.0.3</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

И я буду использовать Lombok и SLF4J:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.25</version>
    <scope>test</scope>
</dependency>

Вот структура моего проекта:

main/java/fr/fxjavadevblog
          +-- VideoGame.java (JPA Entity)
          +-- VideoGameFactory.java
          +-- VideoGameRepository.java (interface)
          +-- InjectedUUID.java (annotation def.)
          +-- Producers.java (produces EntityManager and UUID has string)
    /resources/META-INF
          +-- beans.xml
          +-- persistence.xml

test/java/fr/fxjavadevblog
          +-- VideoGameReposityTest.java (JUnit 5)
    /resources/META-INF
          +-- beans.xml
          +-- persistence.xml

Вот мои производители CDI, необходимые для DeltaSpike Data и для внедрения UUID в качестве закрытых ключей:

package fr.fxjavadevblog;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import java.util.UUID;

/**
 * composite of CDI Producers.
 *
 * @author robin
 */
@ApplicationScoped
public class Producers
{
    public static final String UNIT_NAME = "cdi-deltaspike-demo";

    /**
     * produces the instance of entity manager for the application and for DeltaSpike.
     */
    @Produces
    @SuppressWarnings("unused") // just remove the warning, because the field serves as CDI Producer and the IDE cannot detect it.
    private static EntityManager em = Persistence.createEntityManagerFactory(UNIT_NAME).createEntityManager();

    /**
     * produces randomly generated UUID for primary keys.
     *
     * @return UUID as a HEXA-STRING
     *
     */
    @Produces
    @InjectedUUID
    @SuppressWarnings("unused") // just remove the warning, because the method serves as CDI Producer and the IDE cannot detect it.
    public String produceUUIDAsString()
    {
        return UUID.randomUUID().toString();
    }
}

этот класс использует пользовательский спецификатор CDI с именем @InjectedUUID:

package fr.fxjavadevblog;

import javax.inject.Qualifier;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;


import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * CDI Qualifier for UUID Producers
 *
 * @author robin
 */

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface InjectedUUID 
{
}

Вот моя сущность JPA, использующая аннотации Lombok и CDI:

package fr.fxjavadevblog;

import lombok.*;

import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.persistence.*;
import java.io.Serializable;

/**
 * simple JPA Entity, using Lombok and CDI Injected fields (UUID).
 *
 * @author robin
 */

// lombok annotations
@NoArgsConstructor(access = AccessLevel.PROTECTED) // to avoid direct instanciation bypassing the factory.
@ToString(of = {"id","name"})
@EqualsAndHashCode(of="id")

// CDI Annotation
@Dependent

// JPA Annotation
@Entity
public class VideoGame implements Serializable {

    @Id
    @Inject @InjectedUUID // ask CDI to inject an brand new UUID
    @Getter
    private String id;

    @Getter @Setter
    private String name;

    // this field will work as a flag to know if the entity has already been persisted
    @Version
    @Getter
    private Long version;
}

Вот простая фабрика для моего класса сущности:

/**
 * simple Factory for creation VideoGame instances populated with UUID, ready to persist.
 * This factory is need to get a proper Entity. Entities must not be created with the "new" operator, but must be build
 * by invoking CDI.
 *
 * @author robin
 */
public class VideoGameFactory
{
    /**
     * creates and brand new VideoGame instance with its own UUID as PK.
     *
     * @return instance of a VideoGame
     */
    public static VideoGame newInstance()
    {
        // ask CDI for the instance, injecting required dependencies.
        return CDI.current().select(VideoGame.class).get();
    }
}

И, наконец, DeltaSpike DataResposity для моей сущности:

package fr.fxjavadevblog;

import org.apache.deltaspike.data.api.EntityRepository;
import org.apache.deltaspike.data.api.Repository;


/**
 * CRUD (and much more) interface, using DeltaSpike Data module.
 *
 * @author robin
 */

@Repository
interface VideoGameRepository extends EntityRepository <VideoGame, String>
{
    // nothing to code here : automatic Repo generated by DeltaSpike
}

Вот файлы конфигурации:

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
       bean-discovery-mode="annotated" version="2.0">
</beans>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
                                 http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="cdi-deltaspike-demo" transaction-type="RESOURCE_LOCAL">

        <class>fr.fxjavadevblog.VideoGame</class>

        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test"/>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.schema-generation.database.action" value="create"/>
        </properties>

    </persistence-unit>
</persistence>

Эти файлы также дублируются в папку test / resources / META-INF.

И, наконец, вот модульный тест:

package fr.fxjavadevblog;

import org.jboss.weld.junit5.EnableWeld;
import org.jboss.weld.junit5.WeldInitiator;
import org.jboss.weld.junit5.WeldSetup;
import org.junit.Assert;
import org.junit.jupiter.api.Test;

import lombok.extern.slf4j.Slf4j;

import javax.inject.Inject;

/**
 * simple test class for the VideoGameRepository, using LOMBOK and WELD.
 *
 * @author robin
 */

@Slf4j
@EnableWeld
class VideoGameRepositoryTest
{
    @WeldSetup // This is need to discover Producers and DeltaSpike Repository functionality
    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);
    }

}

Использование Lombok и производителя UUID необязательно.

Вы можете найти полный исходный код и клонировать репозиторий на github: https://github.com/fxrobin/cdi-deltaspike-demo

...