3
votes
<junit printsummary="on" fork="yes" forkmode="once" 
haltonerror="false" haltonfailure="false" 
    failureproperty="junit.failure" showoutput="false" maxmemory="1024m">
    <classpath>
        <path refid="CLASSPATH_JUNIT"/> 
        <dirset dir="${TEST_BUILD_DIR}"/>
    </classpath>            
    <batchtest fork="no"  todir="${TEST_BUILD_DIR}">
         <fileset dir="${COMP_TEST_SRC}">                   
              <include name="**/*Test.java" />
              <include name="**/Test*.java" />
              <exclude name="**/EswTestCase.java" />
         </fileset>             
    </batchtest>    
    <formatter type="xml" />            
</junit>

this takes lot of time to generate xml report, and it thorws following error:

Caught an exception while logging the end of the build.  Exception was:
java.lang.OutOfMemoryError: PermGen space

why it takes long time to genearte xml? how to resolve this error and make application to run fast. I have only max of 10 test files. I use command promt to execute ant script.

Analysis:

1)If i run batch test only for test calss which extends Junit test it execute very fast. eg:

public class ImpactsParserTest extends TestCase{..

2)Now if i have test class which extends spring junit test as:

public class AddressLookupServiceTest extends EswTestCase{..

public class EswTestCase extends AbstractDependencyInjectionSpringContextTests{..

this causes junit target to run very slowly and causes outof memory error. why itis happening like this?

3) when I make batchtest fork="yes" instead of no, then build is quick and doesnt throw outof memory. But, it throws error like:

java.lang.NoClassDefFoundError
at org.apache.log4j.Logger.getLogger(Logger.java:118)
..
java.lang.NoClassDefFoundError: com.bgc.ordering.wizard.back.services.EswTestCase

even though, i have specified these jar file and class file in classpath element as:

and logger jar in

<path id="CLASSPATH_JUNIT">
   <fileset dir="${BUILD_LIBS_HOME}">       
       <include name="*.jar" /> 
   </fileset>
   <pathelement location="${TEST_CLASSES_DIR}" />
   <pathelement location="${TEST_BUILD_DIR}" />
   <pathelement location="${COMP_BUILD}" />     
   <pathelement location="${COMP_CLASSES}" />   
   <path location="${APP_DIR}\bgc-esw-services\target\classes"/> 
   <pathelement location="${APP_DIR}\bgc-esw-web\target\classes" />

...

log4j.properties present at ${TEST_BUILD_DIR}

using: apache-ant-1.8.1 and junit-3.8.1.jar

1

1 Answers

3
votes

This error occurs when the JVM runs out of space in the permanent generation heap. The memory in the Virtual Machine is divided into a number of regions. One of these regions is PermGen. It's an area of memory that is used to (among other things) load class files. The size of this memory region is fixed, i.e. it does not change when the VM is running. You can specify the size of this region with a commandline switch: -XX:MaxPermSize. The default is 64 Mb on the Sun VMs. To fix this issue you can give it a higher value like 256mb.

My guess is that you not only run unit tests you also run integration tests e.g. you have a class wired with Spring and you require their dependencies. That's why you have EswTestCase. If you just want to write unit tests I'd recommend you instantiate your class and mock the dependencies to other classes that you are not testing directly. This will minimize your memory footprint because you don't have to create your Spring application context.

This is what the JavaDoc says about AbstractDependencyInjectionSpringContextTests:

Really for integration testing, not unit testing. You should not normally use the Spring container for unit tests: simply populate your POJOs in plain JUnit tests!

As of Spring 3.0, the legacy JUnit 3.8 base class hierarchy (i.e., AbstractDependencyInjectionSpringContextTests, AbstractTransactionalDataSourceSpringContextTests, etc.) is officially deprecated and will be removed in a later release. It is recommended that you use the Spring TestContext Framework for writing integration tests. Instead of extending EswTestCase with AbstractDependencyInjectionSpringContextTests you should use the annotations.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class EswTestCase 
{
    ...
}