如何从JerseyTest子类访问Spring Bean

时间:2015-12-24 13:21:05

标签: java spring testing jersey jersey-2.0

这是我的抽象类,它使用给定的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

我也发现了一个类似的问题here

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

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

2 个答案:

答案 0 :(得分:1)

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

要做到这一点,没有任何“丑陋的黑客”,你需要掌握ServiceLocator(类似于Spring的ApplicationContext)。当Jersey应用程序启动时,来自ApplicationContext的所有Spring服务都会被放入ServiceLocator到HK2的Spring桥。

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

如果您不知道自己在做什么,尝试实施自己的TestContainerFactory不是在公园散步。最简单的方法就是查看泽西岛InMemoryTestContainerFactory的源代码。如果查看内部类InMemoryTestContainer的构造函数,您将看到它创建ApplicationHandler。这是您通过ServiceLocator公开appHandler.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 project与完整的实现放在一起进行测试。

更新

虽然OP对这个问题的回答是有效的,但我相信它有效的事实是一个错误。在OP公布他们的答案之后我最初删除了这个答案,但经过一些测试后,我认为解决方案是一个bug,所以我已经删除了这个帖子,对于那些不喜欢警告的人来说 1 < / strong> 您在使用该解决方案时获得

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

答案 1 :(得分:1)

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

@Autowired
private Repository repository;

到AbstractJerseyTest,该字段在测试启动期间自动自动装配。我不知道它是如何工作的细节,但似乎当我在REST应用程序中注册测试实例时

application.register(this);

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