Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
210 views
in Technique[技术] by (71.8m points)

java - Spring Integration Test is Slow with Autowiring

I am trying to speed up the Integration tests in our environment. All our classes are autowired. In our applicationContext.xml file we have defined the following:

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

I have noticed that Spring is scanning all directories indicated above and then iterates over each bean and caches the properties of each one. (I went over the DEBUG messages from spring)

As a result, the following test takes about 14 seconds to run:

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

Is there any way to lazy load the configuration? I tried adding default-lazy-init="true" but that didn't work.

Ideally, only the beans required for the test are instantiated.

thanks in advance.

Update: I should have stated this before, I do not want to have a context file for each test. I also do not think one context file for just the tests would work. (This test context file would end up including everything)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you really want to speed up your application context, disable your <component-scan and performs the following routine before running any test

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(); 

Besides that, enable <context:annotation-config/>

As you need to perform the routine above before running any test, you can create an abstract class where you can run the following

Set up a Java system property for testing environment as follows

-Doptimized-application-context=false

And

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"); 
        }

    }

}

Now, for each test class, just extends Initializer


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...