代码之家  ›  专栏  ›  技术社区  ›  x80486

在Java SE上运行单元测试时使用CDI with Weld的不满意依赖关系

  •  0
  • x80486  · 技术社区  · 3 年前

    我有一个小的(Java SE) 11.x )我正在用焊接测试CDI的项目。我有这些依赖项(除其他外,这些是与此问题相关的):

    implementation("org.jboss.weld.se:weld-se-core:4.0.0.Final")
    
    runtimeOnly("javax:javaee-api:8.0.1")
    
    testImplementation("org.jboss.weld:weld-junit5:2.0.2.Final")
    

    然后我有一个简单的实体类:

    @Entity
    @Table(name = "spell_books")
    public final class SpellBook extends AbstractPersistable {
      @Id
      @GeneratedValue(generator = "uuid2")
      @GenericGenerator(name = "uuid2", strategy = "uuid2")
      @Column(name = "id", nullable = false, updatable = false)
      private UUID id;
    
      @Column(name = "name")
      private String name;
    
      // ...some one-to-many and many-to-may relationships
    
      public SpellBook() { // No-args constructor required by JPA
        spells = new LinkedList<>();
        wizards = new LinkedList<>();
      }
    
      public SpellBook(final String name) {
        this();
        this.name = name;
      }
    
      public void add(final Spell spell) {
        spell.setSpellBook(this);
        spells.add(spell);
      }
    }
    
    @MappedSuperclass
    public abstract class AbstractPersistable implements Serializable {
      @Version
      @Column(name = "version")
      private Long version;
    }
    

    ...以及一个与数据库接口的DAO类:

    import jakarta.inject.Singleton;
    import lombok.extern.log4j.Log4j2;
    
    @Log4j2
    @Singleton
    public class SpellBookDao extends AbstractJpaDao<SpellBook> {
      public Optional<SpellBook> findByName(final String name) {
        logger.debug("Searching spell book with name [{}]...", name);
        final var builder = entityManager.getCriteriaBuilder();
        final var criteria = builder.createQuery(clazz);
        final var model = criteria.from(clazz);
        criteria.select(model).where(builder.equal(model.get("name"), name));
        return Optional.ofNullable(entityManager.createQuery(criteria.select(model)).getSingleResult());
      }
    }
    
    @Log4j2
    public abstract class AbstractJpaDao<T extends AbstractPersistable> {
      @PersistenceContext
      protected EntityManager entityManager;
    
      protected Class<T> clazz;
    
      public void setClazz(final Class<T> clazz) {
        this.clazz = clazz;
      }
    
      // ...some defaults for persist, merge, findAll, findOne, etc.
    }
    

    我想做的是为DAO类编写一个简单的单元测试:

    import jakarta.inject.Inject;
    import org.acme.service_layer.persistence.SpellBookDao;
    import org.assertj.core.api.Assertions;
    import org.jboss.weld.junit5.EnableWeld;
    import org.junit.jupiter.api.Disabled;
    import org.junit.jupiter.api.Test;
    
    import java.util.UUID;
    
    @EnableWeld
    final class SpellBookDaoTest {
      @Inject
      private SpellBookDao dao;
    
      @Test
      void findByName_WhenSpellBookExists() {
        final var optional = dao.findByName("The Dark Lord Ascending");
        Assertions.assertThat(optional)
            .hasValueSatisfying(it -> {
              Assertions.assertThat(it.getId()).isEqualTo(UUID.fromString("715811c9-ae11-41ec-8652-671fd88cd2a0"));
              Assertions.assertThat(it.getName()).isEqualTo("The Dark Lord Ascending");
              Assertions.assertThat(it.getSpells()).isEmpty();
              Assertions.assertThat(it.getWizards()).isEmpty();
              // ...
              Assertions.assertThat(it.getVersion()).isEqualTo(0L);
            });
      }
    }
    

    此stacktrace总是失败:

    WELD-001408: Unsatisfied dependencies for type SpellBookDao with qualifiers @Default
      at injection point [BackedAnnotatedField] @Inject private org.acme.service_layer.persistence.internal.SpellBookDaoTest.dao
      at org.acme.service_layer.persistence.internal.SpellBookDaoTest.dao(SpellBookDaoTest.java:0)
    
    org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type SpellBookDao with qualifiers @Default
      at injection point [BackedAnnotatedField] @Inject private org.acme.service_layer.persistence.internal.SpellBookDaoTest.dao
      at org.acme.service_layer.persistence.internal.SpellBookDaoTest.dao(SpellBookDaoTest.java:0)
    
        at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:378)
    
    ...many more here
    

    我已经搜索了很多类似的问题/答案,但仍然不知道我做错了什么。有什么建议吗?

    顺便说一句,我有一个 main/resources/META-INF/beans.xml test/resources/META-INF/beans.xml .两者的内容相同:

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
        bean-discovery-mode="all">
      <scan>
        <exclude name="org.jboss.weld.**" />
      </scan>
    </beans>
    
    0 回复  |  直到 3 年前
        1
  •  1
  •   Siliarus    3 年前

    正如我在报告中所说 GitHub issue 对于这个问题——这是一个问题,因为截至今天(2021年2月23日), weld-junit 版本 2.x 设置为使用Java/Jakarta EE 8。我需要为雅加达EE 9及其应用发布一个新的主要版本 jakarta 由Weld 4实现的名称空间。这应该不会太难,我希望能在一两周内抽出时间。

    编辑: weld junit 3.0.0版。Final现已在Central提供,旨在与雅加达EE 9名称空间配合使用,因此上述问题应得到有效解决。

    在那之前,你只能使用 焊接junit 如果你用它的 javax 名称空间,并使用Weld 3实现。

    最后但并非最不重要的一点是,您的项目混淆了EE8和EE9工件——这是您需要解决的一个问题,主要是因为这两个工件之间的名称空间差异,即使在我们修复之后,也会继续导致问题 焊接junit .

        2
  •  0
  •   Tokazio    3 年前

    我认为,如果您没有使用范围注释对至少一个进行注释,CDI就无法提供实现。 将@ApplicationScoped或@Singleton放在SpellBookDao上

    刚刚看到您已经设置了bean discovery mode=“all”,应该可以工作了。。。

    [编辑]

    Add to your gradle
    test.doFirst {
        copy {
            from 'build/resources/main/META-INF/beans.xml'
            into 'build/classes/main/META-INF/'
        }
        copy {
            from 'build/resources/test/META-INF/beans.xml'
            into 'build/classes/test/META-INF/'
        }
    }
    

    从…起 https://stackoverflow.com/a/20355024/2710704

        3
  •  0
  •   Tokazio    3 年前

    通过以下方式更改您的测试:

    @ExtendWith(WeldJunit5Extension.class)
    final class SpellBookDaoTest {
    
      @WeldSetup
      WeldInitiator weldInitiator =  WeldInitiator.of(SpellBookDao.class);
    

    向gralde配置中的API添加依赖项: `测试实现(“javax:javaeeapi:8.0.1”)``

    你的豆子就会被找到。 现在您必须提供EntityManager。

    我是医生 https://github.com/weld/weld-junit/blob/master/junit5/README.md https://weld.cdi-spec.org/news/2017/12/19/weld-meets-junit5/