【问题标题】:How to access a container managed object from a class that is not managed by the container如何从不受容器管理的类访问容器管理对象
【发布时间】:2015-10-19 13:47:38
【问题描述】:

有没有办法从不是由容器创建或管理的类访问通常由容器创建和管理的对象?换句话说,当有容器时可以使用容器管理的类实例,而没有容器时可以使用常规 POJO?

对我来说关键是测试类不知道它获取的类是来自容器还是只是一些存根。

我可能是老派,但我想使用可配置的工厂类来访问我的数据库。在生产或集成测试中,它将返回我的 DAL 接口的容器注入实现。在进行单元测试时,我想删除 DAL 并返回静态值。

这可能吗?

怎么做?

这是我目前所处的位置,但仍然没有快乐......

工厂类

@Stateless
public class DALFactory
{
   @Inject
   private static DALInterface DAL;

   public static void init(String fqcn)
   {
      // use reflect to create unit test instance
   }

   public static DALInterface getDAL()
   {
      return DAL;
   }
}

测试类

public class test
{
   public void testDALAccess()
   {
      Table t = new Table(); // Instance of class representing a table
      DALFactory.getDAL().persist(t);
   }
}

当我提供我的 testDAL 时,这工作得很好,因为我使用 FQCN 调用 init(),但是当我尝试使用容器托管实例时,它失败了。

您可能会猜到我对 CDI 和 JPA 有点陌生。

仅供参考,我将DALFactory 标记为@Stateless 的唯一原因是,当有容器时,它可以由容器管理。

【问题讨论】:

  • 你可能有一个误解,CDI 的一个重点是利用静态属性。
  • 此外,EJB 和 CDI 是不同的技术,尽管非常相似。 @Stateless 将该类标记为 EJB,但 @Inject 正在寻找 CDI 注入。如果这有效,那很好,但您可能会发现一些不受欢迎的行为。 (如果你想保持一致,你应该使用@SessionScoped而不是@Stateless,或者@EJB而不是@Inject。)
  • @AnthonyRaymond 好的,那么你如何注入一个用于单元测试的接口的测试存根实现呢?我不想在部署到不同的环境之前更改代码,因为我想从存根转移到完整的实现......
  • 注入不应该是单元测试的一部分。单元测试是关于验证方法或类(“单元”)的行为;外部依赖项通常使用 JMockit、Mockito 或 EasyMock 等工具进行模拟,而不是注入。如果您指的是集成测试,那么我建议您使用 Arquillian 之类的工具在容器中运行它们。
  • @dcsohl 好的,但是我如何编写代码以使您不需要注入?以我的具体示例为例 - 我如何编写一个类以便我可以测试它而无需向其中注入任何东西?当调用“testDALAccess()”方法尝试访问数据库但我目前没有提供数据库的容器时,如何测试我的“Test”类?

标签: java jpa cdi


【解决方案1】:

这就是我最终解决问题的方法。完成此操作后,我能够隔离依赖注入的代码和相关容器,以便我可以在没有容器的情况下对其进行测试。

注意 - 我仍然对解决此问题的其他方法持开放态度,这样我就可以在有或没有执行注入的容器的情况下测试相同的代码。

// DAL 工厂

public class DALFactory
{
   private static DALInterface DAL;

   public static void setDAL(DALInterface di)
   {
      DAL = di;
   }

   public static void init(String fqcn)
   {
      // use reflect to create unit test instance
   }

   public static DALInterface getDAL()
   {
      return DAL;
   }
}

// 根可注入类,这必须是可注入树的顶部

@Stateless
public MainClass
{
  @Inject
  ProdDAL dal;

  @PostConstruct
  public void postConstruct()
  {
      DALFactory.setDAL(new DALWrapper(this.dal));
  }
}

// DALWrapper

public DALWrapper implements DALInterface
{
   private ProdDAL dal;

   public DALWrapper(ProdDAL prodDAL)
   {
      this.dal = prodDal;
   }

... rest of interface goes here
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多