我正在尝试创建一个通过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
答案 0 :(得分:0)
我需要将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类。在测试期间,它将从容器实例中设置实体管理器。
@ApplicationScoped
public class JpaProvider {
private EntityManager em;
@Produces
public EntityManager getEntityManager() {
return em;
}
@PersistenceContext
public void setEntityManager(final EntityManager em) {
this.em = em;
}
}
答案 1 :(得分:0)
您的解决方案听起来很笨拙,据我所知,您需要更改测试中的代码(这不是一件好事(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
}
}