How-to: Write test cases that requires disk access

If your test case needs disk access then, the Pineapple test utilities contains a Spring TestExecutionListener implementation, which creates a new directory prior to execution of a test method in a test class. Each test method is then free to create additional sub directories or use files in this directory.

The execution listener can be configured to delete the directory after execution of each test method.

To write unit tests that requires disk access follow these steps:

  • Add Spring-test Maven test dependencies to the project
  • Write the test class

Add Spring-test Maven dependency to the project

The Spring-test jar gives access to:

  • The @TestExecutionListeners annotation.
  • The @ContextConfiguration annotation.

To use the Spring framework test facilities, add the Maven dependency to the project POM:

  <dependency>
    <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <scope>test</scope>
  </dependency>                                                 

Version information is located in the pineapple-project/pom.xml. The dependency is scoped as test as it should only be available in the test phase.

Write the JUnit test class

Create the JUnit test class which should contain the tests which needs access to a separate test directory for each test method.

Configure the class to be run with the Spring JUnit class runner

Annotate the class with the @RunWith( SpringJUnit4ClassRunner.class ) Spring annotation to configure the class to be run with the Spring JUnit class runner.

Example: The integration class BasicHtmlReportGeneratorIntegrationTest in the pineapple-basic-html-report-generator project is configured with:

  • @RunWith( SpringJUnit4ClassRunner.class ) to configure class to be run with Spring Junit test runner.

Configure the class to be run with the proper context configuration

Annotate the class with the @ContextConfiguration( locations = "/some-app-config-config.xml" ) Spring annotation to configure the Spring JUnit class runner to load the application context from the designated location(s).

Example: The integration class BasicHtmlReportGeneratorIntegrationTest in the pineapple-basic-html-report-generator project is configured with:

Configure the class to be run with TestExecutionListener which initializes the test directory

Annotate the class with the @TestExecutionListeners( DirectoryTestExecutionListener.class ) Spring annotation to configure the Spring test runner to use the DirectoryTestExecutionListener class during test execution.

The DirectoryTestExecutionListener class creates a test directory named ${class-name}-${method-name} prior to execution of the test method named ${method-name} in the test class ${class-name}. After execution of the test method the directory is deleted if the DirectoryTestExecutionListener is configured to do so.

Location of the test directory

The test directory is created as a sub directory to the root directory specified by the constant runtimeDirectory defined in the class com.alpha.testutils.TestUtilsTestConstants.

Configure the class to be run with the default Spring TestExecutionListener implementations

Spring 3.0 contains three default TestExecutionListener implementation's which needs to be configured additionally with the @TestExecutionListeners if their functionality should be enabled:

  • DependencyInjectionTestExecutionListener which provides support for dependency injection and initialization of test instances.
  • DirtiesContextTestExecutionListener used with the @DirtiesContext annotation which should if the test modifies the context.
  • TransactionalTestExecutionListener which provides support for executing tests within transactions by using the Spring transactional annotation.

Link to the Spring 3.0 documentation about the default TestExecutionListener implementations.

Please notice: if the test case is a integration test then the DependencyInjectionTestExecutionListener should used to enable the dependency injection.

Access the test directory in the tests

The name of the test directory for the current test method can be looked up from a test method using the static method DirectoryTestExecutionListener.getCurrentTestDirectory().

The method can be invoked in the setUp() for test class, as shown in the example below.

Examples

Example: Running the test with DirectoryTestExecutionListener only

Dependency injection will be disabled in this example.

@RunWith( SpringJUnit4ClassRunner.class )
@TestExecutionListeners( DirectoryTestExecutionListener.class )
@ContextConfiguration( locations = { "/com.alpha.pineapple.report.basichtml-config.xml" } )
public class BasicHtmlReportGeneratorIntegrationTest {
    
    /**
     * Current test directory.
     */
        File testDirectory;
        
        @Before
        public void setUp() throws Exception {
                
                // get the test directory
                testDirectory = DirectoryTestExecutionListener.getCurrentTestDirectory();
        }

        @After
        public void tearDown() throws Exception {
                
                testDirectory = null;
        }

        @Test
        public void testCanCreateSimpleReport() {
                                
                // getting the test directory for this test method
                File rootDirectory = new File(testDirectory, "reports" );                               
        
                // remaining test logic....             
        }
        
}

Example: Running the test with DirectoryTestExecutionListener and DependencyInjectionTestExecutionListener

Dependency injection will be enabled in this example.

@RunWith( SpringJUnit4ClassRunner.class )
@TestExecutionListeners( {DirectoryTestExecutionListener.class, DependencyInjectionTestExecutionListener.class})
@ContextConfiguration( locations = { "/com.alpha.pineapple.report.basichtml-config.xml" } )
public class BasicHtmlReportGeneratorIntegrationTest {
    
    /**
     * Current test directory.
     */
        File testDirectory;
        
        @Before
        public void setUp() throws Exception {
                
                // get the test directory
                testDirectory = DirectoryTestExecutionListener.getCurrentTestDirectory();
        }

        @After
        public void tearDown() throws Exception {
                
                testDirectory = null;
        }

        @Test
        public void testCanCreateSimpleReport() {
                                
                // getting the test directory for this test method
                File rootDirectory = new File(testDirectory, "reports" );                               
        
                // remaining test logic....             
        }
        
}