Results 1 to 7 of 7

Thread: Using a BeanFactory to create Database.

  1. #1
    Join Date
    Jan 2009
    Posts
    10

    Default 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 at 07:59 AM.

  2. #2
    Join Date
    Jan 2009
    Posts
    10

    Default

    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>

  3. #3
    Join Date
    Jan 2009
    Posts
    10

    Default

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

  4. #4
    Join Date
    Jan 2009
    Posts
    10

    Default

    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 at 07:50 AM.

  5. #5
    Join Date
    Jan 2009
    Posts
    10

    Default

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

    Code:
        nearly the same test code just for another dao

  6. #6
    Join Date
    Jan 2009
    Posts
    10

    Default

    Is there something I can do to help you helping me

  7. #7
    Join Date
    Jan 2009
    Posts
    10

    Default

    Solved it myself.

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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •