Announcement Announcement Module
Collapse
No announcement yet.
Using a BeanFactory to create Database. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using a BeanFactory to create Database.

    Hi,

    I try to test my dao's like this:

    TestInfrastructure-configuration.xml(attached) is defining my transactionmanager and datasource.

    As you can see I defined a BeanFactory to create my datasource. The factory parses the schema and the testdata and returns a datasource pointing to an in-memory hsqldb db filled with the data.

    This db is used in my junit tests.
    It worked fine when I was just using one test/application context.

    When I wrote a second, a exception is thrown, because he tries to create the datasource again, while its still running and throws the exception "the table already exists".

    I hope somebody can help me to configure it, so that each testfile uses the same database.
    Last edited by LordNecro; Jan 5th, 2009, 08:59 AM.

  • #2
    My Datasource definition:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:tx="http://www.springframework.org/schema/tx"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    	<bean id="DataSource" class="test.TestDataSourceFactory">
    		<property name="testDatabaseName" value="testdb"/>
    		<property name="schemaLocation" ref="Schema"/>
    		<property name="testDataLocation" ref="TestData"/>
    	</bean>
    	
    	<bean id="Schema" class="org.springframework.core.io.FileSystemResource">
    		<constructor-arg value="src/test/resources/schema.sql"/>
    	</bean>
    	
    	<bean id="TestData" class="org.springframework.core.io.FileSystemResource">
    		<constructor-arg value="src/test/resources/testdata.sql"/>
    	</bean>
    	
    	
    	<bean id="TransactionManager"
    		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    		<property name="dataSource" ref="DataSource" />
    	</bean>
    	
    	<tx:annotation-driven transaction-manager="TransactionManager"/>
    
    </beans>

    Comment


    • #3
      My implementation of the Beanfactory

      Code:
      package test;
      
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStream;
      import java.io.InputStreamReader;
      import java.io.Reader;
      import java.sql.Connection;
      import java.sql.SQLException;
      import java.sql.Statement;
      import java.util.Properties;
      
      import javax.sql.DataSource;
      
      import org.apache.log4j.Logger;
      import org.springframework.beans.factory.FactoryBean;
      import org.springframework.core.io.Resource;
      import org.springframework.jdbc.datasource.DriverManagerDataSource;
      
      
      public class TestDataSourceFactory implements FactoryBean {
      
      	private static Logger logger = Logger.getLogger(TestDataSourceFactory.class);
      
      	// Spring properties
      
      	private String testDatabaseName;
      
      	private Resource schemaLocation;
      
      	private Resource testDataLocation;
      
      
      	private DataSource dataSource;
      
      
      	public void setTestDatabaseName(String testDatabaseName) {
      		this.testDatabaseName = testDatabaseName;
      	}
      
      
      	public void setSchemaLocation(Resource schemaLocation) {
      		this.schemaLocation = schemaLocation;
      	}
      
      
      	public void setTestDataLocation(Resource testDataLocation) {
      		this.testDataLocation = testDataLocation;
      	}
      
      
      	// implementing FactoryBean
      
      	public Object getObject() throws Exception {
      		if (dataSource == null) {
      			initDataSource();
      		}
      		return dataSource;
      	}
      
      	@SuppressWarnings("unchecked")
      	public Class getObjectType() {
      		return DataSource.class;
      	}
      
      	public boolean isSingleton() {
      		return true;
      	}
      
      	
      	private void initDataSource() {
      		// create datasource
      		this.dataSource = createDataSource();
      		if (logger.isDebugEnabled()) {
      			logger.debug("Created in-memory test database '" + testDatabaseName + "'");
      		}
      		// now populate the database by loading the schema and test data
      		populateDataSource();
      		if (logger.isDebugEnabled()) {
      			logger.debug("Exported schema in " + schemaLocation);
      		}
      		if (logger.isDebugEnabled()) {
      			logger.debug("Loaded test data in " + testDataLocation);
      		}
      	}
      
      	private DataSource createDataSource() {
      		DriverManagerDataSource dataSource = new DriverManagerDataSource();
      		// use the HsqlDB JDBC driver
      		dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
      		// have it create an in-memory database
      		dataSource.setUrl("jdbc:hsqldb:mem:" + testDatabaseName);
      		dataSource.setUsername("sa");
      		dataSource.setPassword("");
      		dataSource.setConnectionProperties(
      				(Properties)new Properties().setProperty(
      						"shutdown", "true"));
      		return dataSource;
      	}
      
      	private void populateDataSource() {
      		TestDatabasePopulator populator = new TestDatabasePopulator(dataSource);
      		populator.populate();
      	}
      	
      
      
      	private class TestDatabasePopulator {
      
      		private DataSource dataSource;
      
      
      		public TestDatabasePopulator(DataSource dataSource) {
      			this.dataSource = dataSource;
      		}
      
      
      		public void populate() {			
      			Connection connection = null;
      			try {
      				connection = dataSource.getConnection();
      				if (schemaLocation != null) {
      					createDatabaseSchema(connection);
      				}
      				if (testDataLocation != null) {
      					insertTestData(connection);
      				}
      			} catch (SQLException e) {
      				throw new RuntimeException("SQL exception occurred acquiring connection", e);
      			} finally {
      				if (connection != null) {
      					try {
      						connection.close();
      					} catch (SQLException e) {
      					}
      				}
      			}
      			
      		}
      
      		// create the application's database schema (tables, indexes, etc.)
      		private void createDatabaseSchema(Connection connection) {
      			try {
      				String sql = parseSqlIn(schemaLocation);
      				executeSql(sql, connection);
      			} catch (IOException e) {
      				throw new RuntimeException("I/O exception occurred accessing the database schema file", e);
      			} catch (SQLException e) {
      				throw new RuntimeException("SQL exception occurred exporting database schema", e);
      			}
      		}
      
      		// populate the tables with test data
      		private void insertTestData(Connection connection) {
      			try {
      				String sql = parseSqlIn(testDataLocation);
      				executeSql(sql, connection);
      			} catch (IOException e) {
      				throw new RuntimeException("I/O exception occurred accessing the test data file", e);
      			} catch (SQLException e) {
      				throw new RuntimeException("SQL exception occurred loading test data", e);
      			}
      		}
      
      		// utility method to read a .sql txt input stream
      		private String parseSqlIn(Resource resource) throws IOException {
      			InputStream is = null;
      			String ret="";
      			try {
      				is = resource.getInputStream();
      				Reader reader = new InputStreamReader(is);
      
      				char[] cbuf = new char[4096];
      				while (reader.read(cbuf)!=-1){;
      					ret=ret+ new String(cbuf).trim();
      					cbuf=new char[4096];
      				}
      				return ret;
      			} finally {
      				if (is != null) {
      					is.close();
      				}
      			}
      		}
      
      		// utility method to run the parsed sql
      		private void executeSql(String sql, Connection connection) throws SQLException {
      			Statement statement = connection.createStatement();
      			statement.execute(sql);
      		}
      	}
      }

      Comment


      • #4
        a sample testfile. works fine when surefire runs just this

        Code:
        package test;
        
        import static org.junit.Assert.*;
        
        import java.sql.SQLException;
        
        import javax.annotation.Resource;
        
        import org.junit.Ignore;
        import org.junit.Test;
        import org.junit.runner.RunWith;
        
        
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.beans.factory.annotation.Qualifier;
        import org.springframework.test.context.ContextConfiguration;
        import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
        import org.springframework.test.context.transaction.TransactionConfiguration;
        import org.springframework.transaction.annotation.Transactional;
        
        import dao.interfaces.IRezeptDao;
        import entities.Rezept;
        
        @RunWith(SpringJUnit4ClassRunner.class)
        @ContextConfiguration(
        		locations={"classpath*:TestInfrastructure-configuration.xml",
        				"classpath*:RezepteDAO-configuration.xml",
        				"classpath*:TestsuiteRezepteDao-configuration.xml"})
        @TransactionConfiguration(transactionManager="TransactionManager")
        public class RezepteDaoTest {
        
        	private IRezeptDao rezeptDao;
        	private int anzRezepte;
        	private int anzRezepteAufKarte;
        	private int anzRezepteOhneKarte;
        	private int kartenID;
        	private int loeschID;	
        	private int rezeptID;
        	private Rezept testrezept;
        	private int updateID;
        	/*TESTS*/
        	
        	@Test public void test_getAllRezepte() {
        		try {
        			assertEquals(anzRezepte,rezeptDao.getAllRezepte().size());
        		} catch (Exception e) {
        			fail("Exception was thrown while function:getAllRezepte ");
        		}
        	}
        	
        	@Test public void test_getRezepteAufKarte(){
        		try {
        			assertEquals(anzRezepteAufKarte,rezeptDao.getRezepteaufKarte(kartenID).size());
        		} catch (Exception e) {
        			fail("Exception was thrown while function:getRezepteAufKarte ");
        		}
        	}
        	
        	
        	@Test public void test_getRezepteOhneKarte(){
        		try {
        			assertEquals(anzRezepteOhneKarte,rezeptDao.getRezepteohneKarte().size());
        		} catch (Exception e) {
        			fail("Exception was thrown while function:getRezepteOhneKarte ");
        		}
        	}
        	
        	@Test public void test_getRezeptbyID(){		
        
        		try {	
        			assertEquals(testrezept,rezeptDao.getRezeptbyID(rezeptID));	
        		} catch (Exception e) {
        			fail("Exception was thrown while function:getRezeptbyID");
        		}
        	}
        	@Transactional @Test public void test_deletebyID(){
        		int vorher;		
        		try {
        			vorher=rezeptDao.getAllRezepte().size();
        			rezeptDao.deleteByID(loeschID);
        			assertEquals(vorher-1,rezeptDao.getAllRezepte().size());
        		} catch (Exception e) {
        			fail("Exception was thrown while function:deletebyID");
        		}
        	}
        	
        	@Transactional @Test public void test_updateRezept(){
        		Rezept rezept;
        		try {
        			rezept=rezeptDao.getRezeptbyID(updateID);
        			rezept.setRezeptanweisungen("");
        			rezeptDao.updateRezept(rezept);
        			assertEquals(rezept,rezeptDao.getRezeptbyID(updateID));
        		} catch (SQLException e) {
        			fail("Exception was thrown while function:updateID");
        		}
        	}
        	
        	@Transactional @Test(expected=NullPointerException.class) public void test_updateRezept_ValueNull(){
        		try {			
        			rezeptDao.updateRezept(null);			
        		} catch (SQLException e) {
        			fail("Exception was thrown while function:updateID");
        		}
        	}
        	/*Spring Setter*/	
        	
        	@Autowired	
        	public void setAnzRezepteAufKarte(@Qualifier("anzRezepteAufKarte")Integer anzRezepteAufKarte) {
        		this.anzRezepteAufKarte = anzRezepteAufKarte;
        	}
        	@Autowired
        	public void setAnzRezepteOhneKarte(@Qualifier("anzRezepteOhneKarte")Integer anzRezepteOhneKarte) {
        		this.anzRezepteOhneKarte = anzRezepteOhneKarte;
        	}
        	
        	@Autowired
        	public void setRezeptDao(IRezeptDao rezeptDao) {
        		this.rezeptDao = rezeptDao;
        	}
        	
        	@Autowired
        	public void setAnzRezepte(@Qualifier("anzRezepte")Integer anzRezepte){
        		this.anzRezepte=anzRezepte;
        	}
        	
        	@Autowired
        	public void setKartenID(@Qualifier("kartenID")Integer kartenID){
        		this.kartenID=kartenID;
        	}
        	
        	@Autowired
        	public void setLoeschID(@Qualifier("loeschID")Integer loeschID){
        		this.loeschID=loeschID;
        	}
        	
        	@Autowired
        	public void setRezeptID(@Qualifier("rezeptID")Integer rezeptID){
        		this.rezeptID=rezeptID;
        	}
        	
        	@Autowired
        	public void setTestrezept(@Qualifier("testrezept")Rezept testrezept){
        		this.testrezept=testrezept;
        	}
        	
        	@Autowired
        	public void setUpdateID(@Qualifier("updateID")Integer updateID){
        		this.updateID=updateID;
        	}
        }
        Last edited by LordNecro; Jan 5th, 2009, 08:50 AM.

        Comment


        • #5
          but all tests in this fail because of the recreation of the datasource:

          Code:
              nearly the same test code just for another dao

          Comment


          • #6
            Is there something I can do to help you helping me

            Comment


            • #7
              Solved it myself.

              I just defined my datasource in the factory class as static, which saves my datasource-object for the next testsuite.

              Comment

              Working...
              X