如何在 SE 环境中同时使用 Weld 和 EclipseLink?
How do I use Weld and EclipseLink together in an SE environment?
我正在尝试创建一个通过 JPA 使用 EclipseLink 的单元测试,我注意到我需要将 DAO 注入到侦听器中。代码本身在容器内按预期工作,但我无法对其进行单元测试。
监听器是这样的
@ApplicationScoped
public class ParticipantListener {
@Inject
private ParticipantDAO dao;
@PrePersist
@PreUpdate
void ensureNoDuplicateSin(final Participant e) throws DuplicateSinException {
final Participant bySin = dao.getBySinAndNotSelf(e.getSin(), e);
if (bySin != null && bySin.getId() != e.getId()) {
throw new DuplicateSinException();
}
}
}
当我 运行 在单元测试中 dao
没有被注入。
我的测试初始化如下:
weld = new Weld();
final WeldContainer container = weld.initialize();
vf = Validation.buildDefaultValidatorFactory();
final Map<String, String> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
这显然不应该起作用,因为 em/emf
和 container
之间没有关系
我需要将 javax.persistence.bean.manager
设置为指向 Weld 的 bean 管理器。另外我发现我也
weld = new Weld();
final WeldContainer container = weld.initialize();
final JpaProvider jpaProvider = container.select(JpaProvider.class).get();
final Map<String, Object> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
props.put("javax.persistence.bean.manager", container.getBeanManager());
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
jpaProvider.setEntityManager(em);
此外,我不得不将 DAO 更改为不使用 @PersistenceContext
并使用 @Inject
作为实体管理器并创建 JpaProvider class。在测试期间,它将从容器实例设置实体管理器。
@ApplicationScoped
public class JpaProvider {
private EntityManager em;
@Produces
public EntityManager getEntityManager() {
return em;
}
@PersistenceContext
public void setEntityManager(final EntityManager em) {
this.em = em;
}
}
您的解决方案听起来很笨拙,据我了解您需要更改被测代码(这不是一件好事 (TM))。
而是看看 arquillian (http://arquillian.org/) 和 mockito 的使用。
下面是一些样板代码,展示了我通常如何执行此操作:
@RunWith(Arquillian.class)
public class TestParticipantListener {
// Collection of producer methods and/or static producer fields
// that mock the injected dependencies for the class under test
public static class LocalMocks {
@Produces ParticipantDAO getParticipantDAO() {
ParticipantDAO participantDAO = Mockito.mock(...);
return participantDAO
}
}
@Deployment
public static WebArchive createDeployment() {
PomEquippedResolveStage pom = Maven.resolver().loadPomFromFile("pom.xml");
BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class)
.addDefaultNamespaces().getOrCreateAlternatives()
.up();
WebArchive jar = ShrinkWrap.create(WebArchive.class)
.addAsLibraries(pom.resolve("org.mockito:mockito-core").withTransitivity().asFile())
.addClass(ParticipantListener.class)
.addClass(ParticipantDAO.class)
.addClass(TestParticipantListener.LocalMocks.class)
// ... other dependencies
.addAsWebInfResource(new StringAsset(beansXml.exportAsString()), "beans.xml");
return jar;
}
@Inject ParticipantListener participantListenerUnderTest;
@Test
public void test() {
... whatever your test is, using the injected instance
}
}
我正在尝试创建一个通过 JPA 使用 EclipseLink 的单元测试,我注意到我需要将 DAO 注入到侦听器中。代码本身在容器内按预期工作,但我无法对其进行单元测试。
监听器是这样的
@ApplicationScoped
public class ParticipantListener {
@Inject
private ParticipantDAO dao;
@PrePersist
@PreUpdate
void ensureNoDuplicateSin(final Participant e) throws DuplicateSinException {
final Participant bySin = dao.getBySinAndNotSelf(e.getSin(), e);
if (bySin != null && bySin.getId() != e.getId()) {
throw new DuplicateSinException();
}
}
}
当我 运行 在单元测试中 dao
没有被注入。
我的测试初始化如下:
weld = new Weld();
final WeldContainer container = weld.initialize();
vf = Validation.buildDefaultValidatorFactory();
final Map<String, String> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
这显然不应该起作用,因为 em/emf
和 container
我需要将 javax.persistence.bean.manager
设置为指向 Weld 的 bean 管理器。另外我发现我也
weld = new Weld();
final WeldContainer container = weld.initialize();
final JpaProvider jpaProvider = container.select(JpaProvider.class).get();
final Map<String, Object> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
props.put("javax.persistence.bean.manager", container.getBeanManager());
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
jpaProvider.setEntityManager(em);
此外,我不得不将 DAO 更改为不使用 @PersistenceContext
并使用 @Inject
作为实体管理器并创建 JpaProvider class。在测试期间,它将从容器实例设置实体管理器。
@ApplicationScoped
public class JpaProvider {
private EntityManager em;
@Produces
public EntityManager getEntityManager() {
return em;
}
@PersistenceContext
public void setEntityManager(final EntityManager em) {
this.em = em;
}
}
您的解决方案听起来很笨拙,据我了解您需要更改被测代码(这不是一件好事 (TM))。
而是看看 arquillian (http://arquillian.org/) 和 mockito 的使用。
下面是一些样板代码,展示了我通常如何执行此操作:
@RunWith(Arquillian.class)
public class TestParticipantListener {
// Collection of producer methods and/or static producer fields
// that mock the injected dependencies for the class under test
public static class LocalMocks {
@Produces ParticipantDAO getParticipantDAO() {
ParticipantDAO participantDAO = Mockito.mock(...);
return participantDAO
}
}
@Deployment
public static WebArchive createDeployment() {
PomEquippedResolveStage pom = Maven.resolver().loadPomFromFile("pom.xml");
BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class)
.addDefaultNamespaces().getOrCreateAlternatives()
.up();
WebArchive jar = ShrinkWrap.create(WebArchive.class)
.addAsLibraries(pom.resolve("org.mockito:mockito-core").withTransitivity().asFile())
.addClass(ParticipantListener.class)
.addClass(ParticipantDAO.class)
.addClass(TestParticipantListener.LocalMocks.class)
// ... other dependencies
.addAsWebInfResource(new StringAsset(beansXml.exportAsString()), "beans.xml");
return jar;
}
@Inject ParticipantListener participantListenerUnderTest;
@Test
public void test() {
... whatever your test is, using the injected instance
}
}