gpt4 book ai didi

unit-testing - 在 JAX-RS 单元测试中连接到 @EJB 或 @PersistenceContext 注入(inject)

转载 作者:行者123 更新时间:2023-12-03 22:45:29 25 4
gpt4 key购买 nike

我很喜欢学习 JAX-RS 和 Jersey,但是我在尝试测试需要注入(inject) DAO 的简单资源时遇到了障碍,如下所示:

@Stateless
@Path("simple")
public class SimpleResource {

@PersistenceContext
private EntityManager em;

// @GET, etc...

}

(我将转向更抽象的 DAO 模式,但问题是一样的,即如何注入(inject) @EJB DAO?)

在我的单元测试中,我使用了在其 web.xml 中配置 Jersey 的嵌入式 Jetty 服务器,我想 Hook 资源的生命周期,以便我可以注入(inject)一个模拟 EntityManager,但我还没有找到一个干净的答案经过大量搜索。你能帮我吗?我遇到的一些可能的方向:

1) 在我的代码中使用 JNDI 上下文查找来获取 DAO bean,并在测试中注册模拟对象。

而不是@EJB 或@PersistenceContext,在资源的构造函数中使用类似这样的东西:
  theDAO = (DAOImpl) new InitialContext().lookup("java:global/EJB/DAOImpl");

但是,这意味着我的测试环境需要支持 JNDI,而在 Jetty 中这样做可能会带来一些痛苦。另外,它不使用干净的注释方法。

2)使用方法注入(inject)。

注入(inject)该方法,以便我可以设置 DAO 后实例化,例如,
@PersistenceContext(name = "persistence/pu00")
public void setPersistenceUnit00(final EntityManager em) {
em00 = em;
}

或者
private MyEjbInterface myEjb;
@EJB(mappedName="ejb/MyEjb")
public void setMyEjb(MyEjb myEjb) {
this.myEjb = myEjb;
}

但是,要做到这一点,我需要 Jersey 实例化的实例,例如 SimpleResource。我怎么得到它?

3)使用反射。

一种 DIY 注入(inject),类似于:
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);
}

同样,我需要 Jersey 实例化的实例。

4) 使用注入(inject)提供程序。

我仍然粗略地了解它是如何工作的,但看起来 Jersey 提供了一种定义自定义可注入(inject)注释的方法,例如,
    @Provider
public class EJBProvider implements InjectableProvider<EJB, Type> {

public ComponentScope getScope() {
return ComponentScope.Singleton;
}

public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
if (!(t instanceof Class)) {
return null;
}
try {
Class c = (Class) t;
Context ic = new InitialContext();
final Object o = ic.lookup(c.getName());
return new Injectable<Object>() {
public Object getValue() {
return o;
}
};
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

使用辅助类的变体:
Server server = new Server(8080);
Context root = new Context(server,"/",Context.SESSIONS);

ResourceConfig rc = new PackagesResourceConfig("edu.mit.senseable.livesingapore.platform.restws.representations");
rc.getSingletons().add(new SingletonTypeInjectableProvider<javax.ws.rs.core.Context, Myobj>(Myobj.class, new Myobj(12,13)){});

root.addServlet(new ServletHolder(new ServletContainer(rc)), "/");
server.start();

有了这个用途:
@Path("/helloworld")
public class HelloWorldResource {
@Context Myobj myClass;
....
}

这对@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;
}
}

6)扩展ServletContainer。

使用 InjectableProvider 的旧风格?看起来更复杂:
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;
}
};
}
});
}
}

7) 使用嵌入式 EJB 容器。

例如, http://openejb.apache.org .这很重,我预计开始工作会很困惑。 (事实上​​,让我走上“Jetty + Jersey”路线的原因是 GlassFish Embedded 中围绕安全登录的一个错误。我还查看了其他 Java EE 6 应用程序容器,如 JBoss AS,但每个都在嵌入式模式下存在问题,用户受限社区支持。)

8) 使用第三方 IoC 库,如 Spring 或 Guice。

Spring 显然通常用于解决这类问题(在单元测试时注入(inject)模拟),但我想避免不得不学习另一组 API ——纯 Java EE 已经足够挑战了!但如果这是最好的解决方案,我很乐意。我还没有仔细研究过 Spring 或 Guice。

你成功使用过这些吗?您喜欢其他任何解决方案吗?我真的很期待您对此的建议。提前致谢——马特

最佳答案

由于您使用的是 Netbeans,请尝试一下:

Using the Embedded EJB Container to Test Enterprise Applications

本教程使用嵌入式 Glassfish 容器并注入(inject)一个封装 EntityManager 的 EJB(类似于您在第一个选项中描述的内容)。

关于unit-testing - 在 JAX-RS 单元测试中连接到 @EJB 或 @PersistenceContext 注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11562367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com