繁体   English   中英

如何从JerseyTest子类访问Spring Bean

[英]How to access Spring Bean from JerseyTest subclass

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

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;
}
}

因此,问题在于我需要从测试中访问Spring bean,以使用一些数据填充数据库。

球衣版本是2.6

我也在这里找到了类似的问题

但这与Jersey 1.x有关,因此不适用于Jersey 2.x

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

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

为了做到这一点而没有任何“丑陋的hack”,您将需要在ServiceLocator上获得一个句柄(类似于Spring的ApplicationContext )。 当Jersey应用启动时,来自ApplicationContext所有Spring服务都将通过HK2的Spring桥放入ServiceLocator

问题是JerseyTest不会以任何方式公开ServiceLocator 我想得到它的唯一方法是创建自己的TestContainerFactory ,并创建ApplicationHandler ,从而公开ServiceLocator

如果您不知道自己在做什么,尝试实现自己的TestContainerFactory并不是在公园里散步。 最简单的方法是查看Jersey的InMemoryTestContainerFactory的源代码。 如果查看内部类InMemoryTestContainer的构造函数,您会看到它正在创建ApplicationHandler 这是通过appHandler.getServiceLocator()公开ServiceLocatorappHandler.getServiceLocator()

因此,如果复制了该类并公开了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 ,如果需要,还可以将其公开给测试类。

如果您想看一下,我将GitHub项目和一个完整的实现一起进行了测试。


UPDATE

尽管OP对这个问题的回答是可行的,但我相信它可行的事实是一个错误。 我最初在OP发布他们的答案后删除了这个答案,但是经过一些测试,我相信该解决方案是一个错误,因此对于那些不喜欢警告1的人,我已取消删除该帖子。


1.“警告:在SERVER运行时中注册的提供者SimpleTest不会实现在SERVER运行时中适用的任何提供者接口。由于约束配置问题,提供者SimpleTest将被忽略。”

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

@Autowired
private Repository repository;

到AbstractJerseyTest,并且该字段在测试启动过程中自动自动接线。 我不知道有关其工作原理的详细信息,但似乎当我在REST应用程序中注册测试实例时

application.register(this);

它会自动为测试中的所有bean自动布线。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM