Writing integration tests with Spring

Spring provides the module or utility library for integration tests. The following are the steps to write JUnit tests using the Spring transaction management API and SpringJUnit4ClassRunner:

  1. Spring supports XML-based configuration and wiring beans. Create an XML file named integration.xml in the integration source package. Modify the XML file and define the dataSource, transactionManager, and JdbcTemplate Spring beans. The following is the XML body:
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
     
      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"/>
        <property name="url" value="jdbc:derby:derbyDB;create=true"/>
        <property name="username" value="dbo"/>
      </bean> 
     
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="dataSource"/>
      </bean>
        
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
      </bean>
    </beans>

    Tip

    To find out more about Spring beans, visit http://docs.spring.io/spring/docs/1.2.9/reference/beans.html.

    A dataSource bean is defined with driverClassName, url, and username. The dataSource reference is passed to the jdbcTemplate and transactionManager beans.

  2. Spring supports automatic transaction rollback after test execution. It helps us to shield the development database against getting corrupted. The test runner needs to have a reference to a transaction manager bean before test execution. SpringJUnit4ClassRunner handles the integration tests. Add a PhoneBookDerbySpringDaoIntegrationTest JUnit test and add the following lines to it:
    @ContextConfiguration({ "classpath:integration.xml" })
    @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
    @Transactional
    @RunWith(SpringJUnit4ClassRunner.class)
    public class PhoneBookDerbySpringDaoIntegrationTest {
    
      @Autowired
      JdbcTemplate jdbcTemplate;
    
      PhoneBookDerbySpringDao springDao;
    
      @Before
      public void init() {
        springDao = new PhoneBookDerbySpringDao(jdbcTemplate);
      }
    
      @Test
      public void integration() throws Exception {
        PhoneEntry entry = newEntry("12345", "John", "Smith");
    
        //create
        assertTrue(springDao.create(entry));
    
        //retrieve
        List<PhoneEntry> phoneEntries = 
          springDao.searchByFirstName("John");
    
        //verify create
        assertFalse(phoneEntries.isEmpty());
    
        //modify last name
        entry.setLastName("Kallis");
    
        //update
        assertTrue(springDao.update(entry));
    
        //retrieve
        phoneEntries = springDao.searchByFirstName("John");
    
        //verify update
        assertFalse(phoneEntries.isEmpty());
        assertEquals("Kallis", 
          phoneEntries.get(0).getLastName());
    
        //delete
        springDao.delete(entry.getPhoneNumber());
    
        //retrieve
        phoneEntries = springDao.searchByFirstName("John");
    
        //verify delete
        assertTrue(phoneEntries.isEmpty());
      }
    }

The @ContextConfiguration({ "classpath:integration.xml" }) annotation instructs the JUnit runner to load Spring beans from a classpath location. It will load three beans from the integration.xml file.

The class level @Transactional annotation makes all methods transactional.

The @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) annotation defines the transaction manager, and the defaultRollback attribute tells the transaction manager to roll back all transactions after the end of a given test.

The following things happen when the JUnit test is run:

  • Spring beans are loaded from the integration.xml file.
  • A transaction manager is configured to roll back all transactions.
  • The jdbcTemplate bean is automatically wired to the test class member jdbcTemplate.
  • The init method creates a new instance of the dao class and passes the jdbcTemplate bean to the dao.
  • The test first executes and then creates, updates, and deletes PhoneEntry.
  • After test execution, the transaction manager rolls back the transaction. No data is created or modified or deleted from or to the PhoneBook table.

When the JUnit test runs, the following Spring console log is shown:

INFO: Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@569c60]; rollback [true]
Apr 11, 2014 10:02:25 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [[TestContext@134eb84 testClass = PhoneBookDerbySpringDaoIntegrationTest, testInstance = com.packt.database.dao.PhoneBookDerbySpringDaoIntegrationTest@1522de2, testMethod = integration@PhoneBookDerbySpringDaoIntegrationTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@425743 testClass = PhoneBookDerbySpringDaoIntegrationTest, locations = '{classpath:integration.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]]

The log shows that a transaction has begun, and finally the transaction is rolled back. However, the transaction was not rolled back due to any exception, rather it got rolled back due to the transactional setting [defaultRollback = true]. The log shows that testException is equal to null, which implies that no exception was thrown.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset