Java 如何从JerseyTest子类访问Springbean

Java 如何从JerseyTest子类访问Springbean,java,spring,testing,jersey,jersey-2.0,Java,Spring,Testing,Jersey,Jersey 2.0,下面是我的抽象类,它从给定的Spring上下文开始: public abstract class AbstractJerseyTest extends JerseyTest { public void setUp() throws Exception { super.setUp(); } @AfterClass public void destroy() throws Exception { tearDown(); } @Override protected URI get

下面是我的抽象类,它从给定的Spring上下文开始:

public abstract class AbstractJerseyTest extends JerseyTest {

public void setUp() throws Exception {
    super.setUp();
}

@AfterClass
public void destroy() throws Exception {
    tearDown();
}

@Override
protected URI getBaseUri() {
    return URI.create("http://localhost:9993");
}

@Override
protected Application configure() {
    RestApplication application = new RestApplication();

    Map<String, Object> properties = new HashMap<String, Object>();
    properties.put(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
    properties.put("contextConfigLocation", "classpath:spring-context-test.xml");

    application.setProperties(properties);
    application.register(this);
    return application;
}
}
公共抽象类AbstractJerseyTest扩展了JerseyTest{
public void setUp()引发异常{
super.setUp();
}
@下课
public void destroy()引发异常{
撕裂();
}
@凌驾
受保护的URI getBaseUri(){
返回URI.create(“http://localhost:9993");
}
@凌驾
受保护的应用程序配置(){
RestApplication application=新的RestApplication();
映射属性=新的HashMap();
properties.put(ServerProperties.BV_在_响应中发送_错误,true);
put(“contextConfigLocation”,“classpath:spring context test.xml”);
应用程序。设置属性(属性);
申请登记(本);
退货申请;
}
}
所以,问题是我需要从测试中访问Springbean,用一些数据填充数据库

泽西版本是2.6

我还发现了一个类似的问题

但它与Jersey 1.x有关,所以它不适用于Jersey 2.x


有人能给我指出正确的方向吗?

通常在您的情况下,我只会说使用mock,但在某些情况下,您可能需要在测试类中公开服务

public abstract class AbstractServiceLocatorAwareJerseyTest extends JerseyTest {
    
    private final ServiceLocatorAwareInMemoryTestContainerFactory factory
            = new ServiceLocatorAwareInMemoryTestContainerFactory();
    private ServiceLocator locator;
    
    @Override
    public TestContainerFactory getTestContainerFactory() {
        return factory;
    }
    
    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
        this.locator = factory.getServiceLocator();
        if (injectTestClass()) {
            this.locator.inject(this);
        }
    }
    
    public boolean injectTestClass() {
        return true;
    }
    
    public ServiceLocator getServiceLocator() {
        return locator;
    }
}
要做到这一点而不出现任何“丑陋的黑客行为”,您需要获得
ServiceLocator
(类似于Spring的
ApplicationContext
)的句柄。当Jersey应用程序启动时,来自
ApplicationContext
的所有Spring服务将通过HK2的Spring bridge放入
ServiceLocator

问题在于
JerseyTest
不会以任何方式暴露
ServiceLocator
。我能想到的唯一方法是创建自己的
TestContainerFactory
,并创建
ApplicationHandler
,它公开了
ServiceLocator

如果您不知道自己在做什么,那么尝试实现自己的
TestContainerFactory
并不是一件轻而易举的事。最简单的方法就是查看Jersey的源代码。如果查看内部类
InMemoryTestContainer
的构造函数,您将看到它创建了
ApplicationHandler
。这就是如何通过
appHandler.getServiceLocator()
公开
ServiceLocator

因此,如果复制了该类,并公开了
ServiceLocator
,则可以创建
JerseyTest
扩展,并调用
ServiceLocator.inject(Object)
方法来注入测试类

public abstract class AbstractServiceLocatorAwareJerseyTest extends JerseyTest {
    
    private final ServiceLocatorAwareInMemoryTestContainerFactory factory
            = new ServiceLocatorAwareInMemoryTestContainerFactory();
    private ServiceLocator locator;
    
    @Override
    public TestContainerFactory getTestContainerFactory() {
        return factory;
    }
    
    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
        this.locator = factory.getServiceLocator();
        if (injectTestClass()) {
            this.locator.inject(this);
        }
    }
    
    public boolean injectTestClass() {
        return true;
    }
    
    public ServiceLocator getServiceLocator() {
        return locator;
    }
}
如果出于任何原因需要它,那么
ServiceLocator
还具有
ApplicationContext
,如果需要,您还可以将其公开给测试类

如果你想看的话,我把一个完整的实现和测试放在一起


更新 虽然OP对这个问题的回答是有效的,但我相信它有效的事实是一个bug。在OP发布了他们的答案后,我最初删除了这个答案,但是经过一些测试,我相信这个解决方案是一个bug,所以我为那些不喜欢使用该解决方案时得到的警告1的人取消了这篇帖子



一,。“警告:在服务器运行时中注册的提供程序SimpleTest未实现任何适用于服务器运行时的提供程序接口。由于约束配置问题,将忽略提供程序SimpleTest。”

解决方案非常简单。 我补充说:

到AbstractJersey测试,此字段在测试启动期间自动连接。我不知道它是如何工作的,但当我在REST应用程序中注册测试实例时

application.register(this);

它会自动连接测试中的所有bean。

请查看我发布的答案。有时我会错过显而易见的事情。我甚至没有注意到你注册了测试类。这很有道理。事实上,经过进一步的测试,我相信这是一个错误,这是可行的。这肯定不是一项功能,因为我收到一条日志警告:“警告:在服务器运行时注册的提供程序SimpleTest不会实现任何适用于服务器运行时的提供程序接口。由于约束配置问题,将忽略提供程序SimpleTest。”。你收到同样的警告了吗?我说这是一个bug,因为即使类被注入,它也没有注册为一个可以注入到其他东西中的服务。“我得多调查一下。”皮斯基勒,我没有发现你提到的警告。但是,它可能与记录器设置有关。