【问题标题】:How can I enable CDI with Jersey Test Framework?如何使用 Jersey 测试框架启用 CDI?
【发布时间】:2015-04-23 09:13:14
【问题描述】:

我找到了How can I inject a data source dependency into a RESTful web service with Jersey (Test Framework)?,但我想我会问一些不同的问题。

这是@PostConstruct of abstract ancestors are not invoked的后续问题

我编写了一个 JAX-RS 库,并尝试使用 Jersey Test Framework 进行单元测试。

我似乎 HK2 注入正确。但是我发现我的一些生命周期拦截器方法用@PostConstruct@PreDestroy 注释没有被调用(或只有一些被调用)。

public class MyResource {

    @PostConstruct
    private void constructed() { // not invoked
    }

    @Inject
    private Some some; // injection works.
}

如何使用 Jersey 测试框架启用 CDI?我必须依赖什么样的工件?

这是我当前的依赖项。

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>javax.ws.rs</groupId>
  <artifactId>javax.ws.rs-api</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.glassfish.jersey.test-framework.providers</groupId>
  <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
  <scope>test</scope>
</dependency>

【问题讨论】:

    标签: unit-testing jersey testng cdi weld


    【解决方案1】:

    我找到了解决办法。

    我添加了以下附加依赖项。

    <dependency>
      <groupId>org.glassfish.jersey.ext.cdi</groupId>
      <artifactId>jersey-cdi1x</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.glassfish.jersey.ext.cdi</groupId>
      <artifactId>jersey-weld2-se</artifactId>
      <scope>test</scope>
    </dependency>
    

    我认为现在 Weld 接管了 HK2。我不知道jersey-cdi1x-ban-custom-hk2-binding 是干什么用的。无论如何,我可以使用来自javax.enterprise:cdi-api 的标准注释。

    public class MyProducer {
    
        @Produces @Some
        public MyType produceSome() {}
    
        public void disposeSome(@Disposes @Some MyType instance) {}
    }
    

    并添加了 Weld 的初始化代码。

    @Override
    protected Application configure() {
    
        // this method works somewhat weirdly.
        // local variables including logger
        // is null in here
        // I have to start (and join) a thread
        // which initializes Weld and adds a shutdown hook
    
        final Thread thread = new Thread(() -> {
            final Weld weld = new Weld();
            weld.initialize();
            Runtime.getRuntime().addShutdownHook(
                new Thread(() -> weld.shutdown()));
        });
        thread.start();
        try {
            thread.join();
        } catch (final InterruptedException ie) {
            throw new RuntimeException(ie);
        }
    
        final ResourceConfig resourceConfig
            = new ResourceConfig(MyResource.class);
    
        resourceConfig.register(MyProducer.class);
    
        return resourceConfig;
    }
    

    每个点都被注入并调用所有生命周期方法。耶!!!


    我不明白为什么我首先尝试使用线程。

    @Override
    protected Application configure() {
    
        final Weld weld = new Weld();
        weld.initialize();
        Runtime.getRuntime().addShutdownHook(new Thread(() -> weld.shutdown()));
    
        final ResourceConfig resourceConfig
            = new ResourceConfig(MyResource.class);
    
        resourceConfig.register(MyProducer.class);
    
        return resourceConfig;
    }
    

    由于我使用了JerseyTestNg.ContainerPerClassTest,因此我无法使用@BeforeClass@AfterClass,至少在使用TestNG 时失败了,因为configure() 方法是从构造函数中(间接)调用的。

    如果我切换到JerseyTestNg.ContainerPerMethodTest,我想我可以使用@BeforeMethod@AfterMethod 来初始化/关闭焊接。


    jersey-cdi1xjersey-weld2-se 的传递依赖,因此可以省略。

    【讨论】:

    • 只是好奇,您是否简单地尝试过@BeforeClass@AfterClass 带注释的方法来初始化和关闭焊接?由于这是一个测试类,看起来很合适
    • @peeskillet 我发现configure() 显然是从JerseyTest 类的构造函数间接调用的。这就是为什么事件logger 在该方法中不可用的原因。
    • 我的意思是 JUnit 测试提供了 @BeforeClass@AfterClass 注释,您可以将它们放在测试类中的任意静态方法上。前者将在测试开始之前调用,后者在之后调用。而不是线程,我只是想知道是否有一个静态 Weld 字段,在 before 方法中启动它,并在 after 方法中关闭它。
    • @peeskillet 不幸的是,我使用了 TestNG。我尝试使用静态字段和org.testng.annotations.BeforeClass。甚至@BeforeClass 似乎在实例化后也适用。我不确定 JUnit 的工作方式是否不同。
    猜你喜欢
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多