복붙노트

[SPRING] Autowiring으로 Spring 통합 테스트가 느립니다.

SPRING

Autowiring으로 Spring 통합 테스트가 느립니다.

우리 환경에서 통합 테스트의 속도를 높이려고합니다. 모든 수업은 자동으로 실행됩니다. applicationContext.xml 파일에서 다음을 정의했습니다.

<context:annotation-config/>
<context:component-scan base-package="com.mycompany.framework"/>
<context:component-scan base-package="com.mycompany.service"/>
...additional directories

나는 Spring이 위에 표시된 모든 디렉토리를 스캔 한 다음 각 빈에 대해 반복하고 각각의 속성을 캐시한다는 것을 알아 챘다. (봄부터 DEBUG 메시지를 보냈습니다)

결과적으로 다음 테스트를 실행하는 데 약 14 초가 걸립니다.

public class MyTest extends BaseSpringTest {
  @Test
  def void myTest(){
    println "test"
  }
}

구성을 게으른로드 할 수있는 방법이 있습니까? default-lazy-init = "true"를 추가하려고 시도했지만 작동하지 않았습니다.

이상적으로는 테스트에 필요한 bean만이 인스턴스화됩니다.

미리 감사드립니다.

업데이트 : 이전에 언급 했어야했는데 각 테스트에 대한 컨텍스트 파일을 갖고 싶지 않았습니다. 또한 테스트를위한 하나의 컨텍스트 파일이 작동하지 않을 것이라고 생각합니다. (이 테스트 컨텍스트 파일은 모든 것을 포함하여 끝날 것입니다)

해결법

  1. ==============================

    1.애플리케이션 컨텍스트의 속도를 높이려면 을 비활성화하고 테스트를 실행하기 전에 다음 루틴을 수행하십시오

    애플리케이션 컨텍스트의 속도를 높이려면 을 비활성화하고 테스트를 실행하기 전에 다음 루틴을 수행하십시오

    Resource resource = new ClassPathResource(<PUT_XML_PATH_RIGHT_HERE>); // source.xml, for instance
    InputStream in = resource.getInputStream();
    
    Document document = new SAXReader().read(in);
    Element root  = document.getRootElement();
    
    /**
      * remove component-scanning
      */
    for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
        Element element = (Element) i.next();
    
        if(element.getNamespacePrefix().equals("context") && element.getName().equals("component-scan"))
            root.remove(element);
    }
    
    in.close();
    
    ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true);
    for (String source: new String[] {"com.mycompany.framework", "com.mycompany.service"}) {
        for (BeanDefinition bd: scanner.findCandidateComponents(source)) {
            root
            .addElement("bean")
            .addAttribute("class", bd.getBeanClassName());
        }
    }
    
    //add attribute default-lazy-init = true
    root.addAttribute("default-lazy-init","true");
    
    /**
      * creates a new xml file which will be used for testing
      */ 
    XMLWriter output = new XMLWriter(new FileWriter(<SET_UP_DESTINATION_RIGHT_HERE>));
    output.write(document);
    output.close(); 
    

    그 외에도 를 활성화하십시오.

    테스트를 실행하기 전에 위의 루틴을 수행해야하므로 다음을 실행할 수있는 추상 클래스를 작성할 수 있습니다

    다음과 같이 환경 테스트 용 Java 시스템 특성을 설정하십시오.

    -Doptimized-application-context=false
    

    public abstract class Initializer {
    
        @BeforeClass
        public static void setUpOptimizedApplicationContextFile() {
            if(System.getProperty("optimized-application-context").equals("false")) {
                // do as shown above
    
                // and
    
                System.setProperty("optimized-application-context", "true"); 
            }
    
        }
    
    }
    

    이제 각 테스트 클래스에 대해 Initializer를 확장합니다.

  2. ==============================

    2.한 가지 방법은 자동 검색을 완전히 건너 뛰고 런타임에 (테스트 실행 전에) 빈을 다시 정의하거나 별도의 컨텍스트를로드하는 것입니다.

    한 가지 방법은 자동 검색을 완전히 건너 뛰고 런타임에 (테스트 실행 전에) 빈을 다시 정의하거나 별도의 컨텍스트를로드하는 것입니다.

    이 스레드는 빈의 재정의와이를 수행하기위한 사용자 정의 테스트 클래스에 대해 설명합니다.

    단위 테스트 환경에서 스프링 빈 재 정의

  3. ==============================

    3.이것은 구성 요소 자동 감지에 대해 지불하는 가격입니다. 속도가 느립니다. 테스트에는 특정 빈이 필요하지만, 은 훨씬 더 광범위하며, Spring은 발견 한 모든 빈을 인스턴스화하고 초기화 할 것이다.

    이것은 구성 요소 자동 감지에 대해 지불하는 가격입니다. 속도가 느립니다. 테스트에는 특정 빈이 필요하지만, 은 훨씬 더 광범위하며, Spring은 발견 한 모든 빈을 인스턴스화하고 초기화 할 것이다.

    테스트를 위해 다른 bean 파일을 사용하는 것이 좋습니다. 하나는 을 사용하지 않고 테스트 자체에 필요한 bean만을 정의하는 것입니다.

  4. ==============================

    4.아마도 당신이 필요로하는 것은 덜 autowiring을 사용하도록 설정을 리팩터링하는 것입니다. 내 접근 방식은 거의 항상 이름으로 빈을 연결하고, 디자인에 명시 적으로 노력하지만, 동시에 너무 길지도 않고, 사소한 세부 사항을 숨기기 위해 자동 와이어 링을 사용할 때 분명히 사용됩니다.

    아마도 당신이 필요로하는 것은 덜 autowiring을 사용하도록 설정을 리팩터링하는 것입니다. 내 접근 방식은 거의 항상 이름으로 빈을 연결하고, 디자인에 명시 적으로 노력하지만, 동시에 너무 길지도 않고, 사소한 세부 사항을 숨기기 위해 자동 와이어 링을 사용할 때 분명히 사용됩니다.

    추가: 이것이 충분하지 않고 junit을 사용하는 경우 JUnit Addons 프로젝트의 유틸리티를 사용할 수 있습니다. DirectorySuiteBuilder 클래스는 디렉토리 구조에서 테스트 스위트를 동적으로 빌드합니다. 그래서 뭔가를 만들 수 있습니다.

    DirectorySuiteBuilder builder = new DirectorySuiteBuilder();
    Test suite = builder.suite("project/tests");
    

    이 코드보다 Spring 컨텍스트를 초기화하면 모든 테스트를 한 번에 실행할 수 있습니다. 그러나, 각 테스트가 "깨끗한"스프링 컨텍스트를 가정한다면, 아마도 잃어버린 것입니다.

  5. ==============================

    5.이런 상황에서는 균형을 찾아야합니다. 한편으로는 결과를 빨리 얻으려면 최대한 짧은 시간에 테스트를 실행해야합니다. 이는 지속적인 통합 작업을 수행하는 팀 환경에서 작업 할 때 특히 중요합니다. 반면에 테스트 구성을 가능한 한 간단하게 유지하여 테스트 스위트의 유지 관리가 유용하지 않게되는 것은 당연한 것입니다.

    이런 상황에서는 균형을 찾아야합니다. 한편으로는 결과를 빨리 얻으려면 최대한 짧은 시간에 테스트를 실행해야합니다. 이는 지속적인 통합 작업을 수행하는 팀 환경에서 작업 할 때 특히 중요합니다. 반면에 테스트 구성을 가능한 한 간단하게 유지하여 테스트 스위트의 유지 관리가 유용하지 않게되는 것은 당연한 것입니다.

    그러나 하루가 끝나면 자신의 균형을 찾아 결정해야합니다. 몇 가지 테스트를 그룹화하여 테스트 할 수 있도록 몇 가지 컨텍스트 설정 파일을 만드는 것이 좋습니다. 그러면 간단한 테스트만으로도 Spring에서 구성하는 데 오랜 시간이 걸리지 않고 관리 할 수있는 최소한의 구성 파일 수를 유지할 수 있습니다.

  6. ==============================

    6.컨벤션 콩 팩토리는이 문제를 해결하기 위해 고안되었으며 전체 프로세스를 3 배 이상 크게 향상시킵니다.

    컨벤션 콩 팩토리는이 문제를 해결하기 위해 고안되었으며 전체 프로세스를 3 배 이상 크게 향상시킵니다.

  7. ==============================

    7.이 질문에 대한 답변이 없기 때문에 나 자신의 경험을 추가합니다.

    이 질문에 대한 답변이 없기 때문에 나 자신의 경험을 추가합니다.

    내 문제는 Spring, Hibernate 및 EhCache가 내 콘솔을 익숙한 디버그 메시지로 익사 시키려 할 때 그룹화되어 읽을 수없는 로그와 훨씬 나쁜 - 견딜 수없는 낮은 성능을 발생시키는 것입니다.

    로그 레벨 구성을 모두 수정 :

    Logger.getLogger("org.hibernate").setLevel(Level.INFO);
    Logger.getLogger("net.sf.ehcache").setLevel(Level.INFO);
    Logger.getLogger("org.springframework").setLevel(Level.INFO);
    
  8. from https://stackoverflow.com/questions/3756120/spring-integration-test-is-slow-with-autowiring by cc-by-sa and MIT license