Unit testing 在JAX-RS单元测试中连接到@EJB或@PersistenceContext注入
我很喜欢学习JAX-RS和Jersey,但我在尝试测试需要注入DAO的简单资源时遇到了一个障碍,比如:Unit testing 在JAX-RS单元测试中连接到@EJB或@PersistenceContext注入,unit-testing,ejb,jersey,jax-rs,Unit Testing,Ejb,Jersey,Jax Rs,我很喜欢学习JAX-RS和Jersey,但我在尝试测试需要注入DAO的简单资源时遇到了一个障碍,比如: @Stateless @Path("simple") public class SimpleResource { @PersistenceContext private EntityManager em; // @GET, etc... } EntityManagerFactory emf = Persistence.createEntityManagerFactory
@Stateless
@Path("simple")
public class SimpleResource {
@PersistenceContext
private EntityManager em;
// @GET, etc...
}
EntityManagerFactory emf = Persistence.createEntityManagerFactory("your unit name");
EntityManager em = emf.createEntityManager();
(我将转向更抽象的DAO模式,但问题是相同的,即如何注入@EJBDAO?)
在我的单元测试中,我使用了一个嵌入式Jetty服务器,该服务器在其web.xml中配置Jersey,我想连接到资源的生命周期中,这样我就可以注入一个模拟EntityManager,但经过大量搜索,我还没有找到一个清晰的答案。你能帮忙吗?我遇到了一些可能的方向:
1)在我的代码中使用JNDI上下文查找来获取DAOBean,并在测试中注册模拟对象。
在资源的构造函数中使用类似以下内容,而不是@EJB或@PersistenceContext:
theDAO = (DAOImpl) new InitialContext().lookup("java:global/EJB/DAOImpl");
然而,这意味着我的测试环境需要支持JNDI,在Jetty中这样做可能会带来一些麻烦。另外,它没有使用干净的注释方法
2)使用方法注射。
注入到方法中,以便我可以设置DAO后实例化,例如
@PersistenceContext(name = "persistence/pu00")
public void setPersistenceUnit00(final EntityManager em) {
em00 = em;
}
或
然而,要做到这一点,我需要Jersey实例化的实例,例如SimpleResource。我怎么知道
3)使用反射。
一种DIY注射,类似于:
public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) {
Field setId = instanceFieldClass.getDeclaredField(fieldName);
setId.setAccessible(true);
setId.set(instance, fieldValue);
}
这对@EJB或@PersistenceContext可行吗
5)扩展javax.ws.rs.core.Application。
关于这一点,我略知一二,但:
@javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public InjectionApplication() {
// no instance is created, just class is listed
classes.add(BookResource.class);
}
@Override
public Set<Class<?>> getClasses() {
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
@javax.ws.rs.ApplicationPath(“应用程序”)
公共类注入应用程序扩展了javax.ws.rs.core.Application{
private Set singleton=new HashSet();
私有集>();
公共注入应用程序(){
//没有创建实例,只列出了类
添加(booksource.class);
}
@凌驾
public Set如果在嵌入式Jetty容器中只需要一个EntityManager
,为什么要首先使用注入?您只需将一个JPA实现(如eclipselink或hibernate)放在类路径上,配置一个资源本地持久化单元,然后按如下方式获得它:
@Stateless
@Path("simple")
public class SimpleResource {
@PersistenceContext
private EntityManager em;
// @GET, etc...
}
EntityManagerFactory emf = Persistence.createEntityManagerFactory("your unit name");
EntityManager em = emf.createEntityManager();
为了测试JAX-RS类,有一些行为类似于@EJB
的东西(可能是静态DAO工厂?)就足够了
如果您确实希望单元测试尽可能接近JavaEE环境,请考虑使用Arquillian运行它们(http://www.jboss.org/arquillian.html)。它直接在Java EE容器上运行测试-很简单,它有很好的文档。既然您使用的是Netbeans,请尝试一下:
本教程使用嵌入式Glassfish容器并注入一个封装EntityManager的EJB(类似于您在第一个选项中描述的内容).我建议您看看NetBeans向导从数据库生成RESTFul web服务的方式。您可以查看以下链接:谢谢,perissf。实际上,我的项目是从NetBeans生成的向导开始的。我重新阅读了您链接的文章,但我看不出它们是如何解决我的问题的——它们最终拥有了一个JAX-RS资源eds是容器注入的EntityManager,对吗?这里可能缺少一些新的东西。。。
@javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public InjectionApplication() {
// no instance is created, just class is listed
classes.add(BookResource.class);
}
@Override
public Set<Class<?>> getClasses() {
return classes;
}
@Override
public Set<Object> getSingletons() {
return singletons;
}
}
public class ServletAdapter extends ServletContainer {
@Override
protected void configure(ServletConfig servletConfig, ResourceConfig rc, WebApplication wa) {
super.configure(servletConfig, rc, wa);
rc.getSingletons().add(new InjectableProvider<Resource, Type>() {
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
public Injectable<Object> getInjectable(ComponentContext ic, Resource r, Type c) {
final Holder value = new Holder();
Context ctx = new InitialContext();
try {
value.value = ctx.lookup(r.name());
} catch (NamingException ex) {
value.value = ctx.lookup("java:comp/env/" + r.name());
}
return new Injectable<Object>() {
public Object getValue() {
return value.value;
}
};
}
});
}
}
EntityManagerFactory emf = Persistence.createEntityManagerFactory("your unit name");
EntityManager em = emf.createEntityManager();