Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java';s服务加载程序和测试资源_Java_Hibernate_Jpa_Service_Serviceloader - Fatal编程技术网

Java';s服务加载程序和测试资源

Java';s服务加载程序和测试资源,java,hibernate,jpa,service,serviceloader,Java,Hibernate,Jpa,Service,Serviceloader,我有一个web应用程序,它将Hibernate Integrator定义为Java ServiceLoader规范的一部分,如下所示: src/main/resources/META-INF/services/org.hibernate.integrator.spi.integrator # Define integrators that should be instantiated by the ServiceLoader org.emmerich.MyIntegrator #

我有一个web应用程序,它将Hibernate Integrator定义为Java ServiceLoader规范的一部分,如下所示:

src/main/resources/META-INF/services/org.hibernate.integrator.spi.integrator

  # Define integrators that should be instantiated by the ServiceLoader
  org.emmerich.MyIntegrator
  # Empty file to try and overwrite the main deployment description.
这是根据Hibernate指南完成的

我的问题是,当我尝试执行单元测试时,主集成器描述符仍然被解析和实例化。这意味着,因为我在单元测试中模拟了应用程序的很大一部分,所以当集成程序试图运行时,它会遇到错误,导致测试失败

我在测试资源中定义了相同的文件:

src/test/resources/META-INF/services/org.hibernate.integrator.spi.integrator

  # Define integrators that should be instantiated by the ServiceLoader
  org.emmerich.MyIntegrator
  # Empty file to try and overwrite the main deployment description.
但是我发现测试和主集成文件都被解析了

我期望测试资源会覆盖主资源,从而呈现主资源obscolete,但事实并非如此。因为这两个文件都在类路径上(我正在使用surefire插件通过Maven运行测试,它将
测试类
放在类路径上)。类似的情况也发生在
persistence.xml

在我的单元测试环境中,我不希望实例化任何积分器,因为我希望尽可能手动地控制这些bean的构造。假设我正在测试执行单元,我不希望有额外的bean,比如可能影响测试运行的积分器。我认为在单元测试期间,这是一个完全合理的要求。但是,尽管主资源仍然由
ServiceLoader
解析,但这是不可能的

我要做的解决方案是基于这里发布的
persistence.xml
解决方案:

我的问题是,在单元测试期间,是否有比强制重命名更好的方法来排除正在处理的主要资源,特别是在
ServiceLoader
文件的上下文中

要更好地总结一下,请执行以下操作:


当类路径上有两个文件都以相同的服务接口命名时会发生什么?在我看来,这两个文件中的所有服务都是实例化的。似乎没有覆盖。

对于那些感兴趣的人来说,更多的调查会导致这样一个事实:这不是Hibernate真正的问题,而是
ServiceLoader在文件中加载的方式。从:

如果一个特定的具体提供程序类在多个 配置文件,或在同一配置文件中命名 超过一次,则忽略重复项

不幸的是,这只适用于具体的类。因此,如果我在表单中指定同一文件的两个副本:

org.emmerich.MyServiceInterface

  org.emmerich.MyServiceImpl
然后,
MyServiceImpl
只实例化一次。但是,如果我使用两个不同的实现类指定了两个文件,那么这两个实现都将被实例化

这对于单元测试并不太好,因为在单元测试中,您需要对服务的实例化位置进行更精细的控制。我对它背后的设计决策知之甚少,但Hibernate的使用使得单元测试变得更加困难

无论如何,我提出的解决方案是将主要资源的覆盖委托给我控制的文件,比如
properties
文件。在服务内部,我现在检查属性文件中的标志是true还是false。在我的主要资源中,这是真的。在我的测试中,它是假的。因为查找属性会命中类路径上的第一个文件,所以我知道它将获得测试资源。我的结构如下所示:

src
  main
    resources
      META-INF
        services
          org.hibernate.integrator.spi.Integrator # has line MyIntegrator
    application.properties     # shouldIntegrate=true 
  test
    resources
      application.properties   # shouldIntegrate=false
MyIntegrator
中:

public class MyIntegrator implements Integrator {

  @Override
  public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
    if(shouldIntegrate()) {
      // do integration
    }
  }

  private boolean shouldIntegrate() {
    // read Properties file from classpath
    // getClass().getClassLoader().getResourceAsStream("application.properties")
    // return value of "shouldIntegrate"
  }
在测试环境中运行时,属性文件查找指向测试资源。在测试环境之外,它指向主要资源