Неудовлетворенные зависимости с использованием CDI с Weld при запуске модульных тестов на Java SE

У меня небольшой (Java SE 11.x), в котором я тестирую CDI с Weld. У меня есть эти зависимости (среди прочего, но они актуальны для этой проблемы):

      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);
        });
  }
}

Это всегда не работает с этой трассировкой стека:

      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>

3 ответа

Решение

Как я уже говорил в вопросе GitHub по этому вопросу - это проблема, потому что на сегодняшний день (23.02.2021) версия 2.x

настроен на работу с Java / Jakarta EE 8. Мне нужно выпустить новую основную версию для Jakarta EE 9 и ее jakarta пространство имен, реализованное в Weld 4. Это не должно быть слишком сложно, и я надеюсь, что смогу найти для этого время в течение недели или двух.

До тех пор вы можете использовать только в том случае, если переключитесь на EE 8 с его javax

пространства имен, а также использовать Weld 3, который это реализует.

И последнее, но не менее важное: ваш проект смешивает артефакты EE 8 и EE 9 - это проблема, которую вам необходимо решить на вашей стороне, в основном из-за различий в пространстве имен между ними, и будет продолжать вызывать проблемы даже после того, как мы исправим weld-junit

.

Измените свой тест с помощью:

      @ExtendWith(WeldJunit5Extension.class)
final class SpellBookDaoTest {

  @WeldSetup
  WeldInitiator weldInitiator =  WeldInitiator.of(SpellBookDao.class);

Добавьте зависимость к API в конфигурации gralde: `testImplementation (" javax: javaee-api: 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 /

Я думаю, что 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/'
    }
}

С /questions/33040258/kak-provesti-modulnoe-testirovanie-cdi-s-privarkoj/33040278#33040278

Другие вопросы по тегам