10 changed files with 436 additions and 2 deletions
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource; |
||||
import org.springframework.util.ClassUtils; |
||||
|
||||
class HsqlTestDataSourceConfigurer extends TestDataSourceConfigurer { |
||||
|
||||
private static HsqlTestDataSourceConfigurer INSTANCE; |
||||
|
||||
public static synchronized HsqlTestDataSourceConfigurer getInstance() throws ClassNotFoundException { |
||||
if (INSTANCE == null) { |
||||
ClassUtils.forName("org.hsqldb.jdbcDriver", HsqlTestDataSourceConfigurer.class.getClassLoader()); |
||||
INSTANCE = new HsqlTestDataSourceConfigurer(); |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
public void configureConnectionProperties(SimpleDriverDataSource dataSource, String databaseName) { |
||||
dataSource.setDriverClass(org.hsqldb.jdbcDriver.class); |
||||
dataSource.setUrl("jdbc:hsqldb:mem:" + databaseName); |
||||
dataSource.setUsername("sa"); |
||||
dataSource.setPassword(""); |
||||
} |
||||
|
||||
public void shutdown(DataSource dataSource) { |
||||
new JdbcTemplate(dataSource).execute("SHUTDOWN"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
import org.springframework.core.io.ClassPathResource; |
||||
import org.springframework.core.io.Resource; |
||||
import org.springframework.core.io.support.EncodedResource; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; |
||||
|
||||
/** |
||||
* Populates a test DataSource from schema and test-data SQL defined in external resources. |
||||
* By default, looks for a schema.sql file and test-data.sql resource in the root of the classpath. |
||||
* |
||||
* May be configured. |
||||
* Call {@link #setSchemaLocation(Resource)} to configure the location of the database schema file. |
||||
* Call {@link #setTestDataLocation(Resource)} to configure the location of the test data file. |
||||
* Call {@link #setSqlScriptEncoding(String)} to set the encoding for the schema and test data SQL. |
||||
*/ |
||||
public class ResourceTestDatabasePopulator implements TestDatabasePopulator { |
||||
|
||||
private Resource schemaLocation = new ClassPathResource("schema.sql"); |
||||
|
||||
private Resource testDataLocation = new ClassPathResource("test-data.sql"); |
||||
|
||||
private String sqlScriptEncoding; |
||||
|
||||
/** |
||||
* Sets the location of .sql file containing the database schema to create. |
||||
* @param schemaLocation the path to the db schema definition |
||||
*/ |
||||
public void setSchemaLocation(Resource schemaLocation) { |
||||
this.schemaLocation = schemaLocation; |
||||
} |
||||
|
||||
/** |
||||
* Sets the location of the .sql file containing the test data to load. |
||||
* @param testDataLocation the path to the db test data file |
||||
*/ |
||||
public void setTestDataLocation(Resource testDataLocation) { |
||||
this.testDataLocation = testDataLocation; |
||||
} |
||||
|
||||
/** |
||||
* Specify the encoding for SQL scripts, if different from the platform encoding. |
||||
*/ |
||||
public void setSqlScriptEncoding(String sqlScriptEncoding) { |
||||
this.sqlScriptEncoding = sqlScriptEncoding; |
||||
} |
||||
|
||||
public void populate(JdbcTemplate template) { |
||||
createDatabaseSchema(template); |
||||
insertTestData(template); |
||||
} |
||||
|
||||
// create the application's database schema (tables, indexes, etc.)
|
||||
private void createDatabaseSchema(JdbcTemplate template) { |
||||
// TODO SimpleJdbcTemplate is unnecessary now with Java5+ - make similar method available on JdbcTestUtils?
|
||||
SimpleJdbcTestUtils.executeSqlScript(new SimpleJdbcTemplate(template), new EncodedResource(schemaLocation, sqlScriptEncoding), false); |
||||
} |
||||
|
||||
// populate the tables with test data
|
||||
private void insertTestData(JdbcTemplate template) { |
||||
// TODO SimpleJdbcTemplate is unnecessary now with Java5+ - make similar method available on JdbcTestUtils?
|
||||
SimpleJdbcTestUtils.executeSqlScript(new SimpleJdbcTemplate(template), new EncodedResource(testDataLocation, sqlScriptEncoding), false); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource; |
||||
|
||||
/** |
||||
* Encapsulates the configuration required to connect to a specific type of test database such as HSQLdb or H2. |
||||
* Create a subclass for each database type we wish to support. |
||||
* |
||||
* @see TestDataSourceConfigurerFactory |
||||
*/ |
||||
abstract class TestDataSourceConfigurer { |
||||
|
||||
/** |
||||
* Configure the properties required to connect to databaseName. |
||||
* @param dataSource the data source to configure |
||||
* @param databaseName the name of the test database |
||||
*/ |
||||
public abstract void configureConnectionProperties(SimpleDriverDataSource dataSource, String databaseName); |
||||
|
||||
/** |
||||
* Shutdown the test database backed by dataSource. |
||||
* @param dataSource the data source |
||||
*/ |
||||
public abstract void shutdown(DataSource dataSource); |
||||
|
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
class TestDataSourceConfigurerFactory { |
||||
|
||||
public static TestDataSourceConfigurer getConfigurer(TestDatabaseType type) throws IllegalStateException { |
||||
try { |
||||
if (type == TestDatabaseType.HSQL) { |
||||
return HsqlTestDataSourceConfigurer.getInstance(); |
||||
} else { |
||||
throw new UnsupportedOperationException("Other types not yet supported"); |
||||
} |
||||
} catch (ClassNotFoundException e) { |
||||
throw new IllegalStateException("Drivers for test database type [" + type + "] are not available in the classpath", e); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,143 @@
@@ -0,0 +1,143 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
import javax.sql.DataSource; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager; |
||||
import org.springframework.jdbc.datasource.SimpleDriverDataSource; |
||||
import org.springframework.transaction.TransactionStatus; |
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult; |
||||
import org.springframework.transaction.support.TransactionTemplate; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Returns a {@link DataSource} that connects to an in-memory test database pre-populated with test data. |
||||
* When the DataSource is returned, callers are guaranteed that the database schema and test data will have already been loaded. |
||||
* |
||||
* Can be configured. |
||||
* Call {@link #setDatabaseName(String)} to change the name of the test database. |
||||
* Call {@link #setDatabaseType(TestDatabaseType)} to set the test database type. |
||||
* Call {@link #setDatabasePopulator(TestDatabasePopulator)} to change the algorithm used to populate the test database. |
||||
*/ |
||||
public class TestDataSourceFactory { |
||||
|
||||
private static Log logger = LogFactory.getLog(TestDataSourceFactory.class); |
||||
|
||||
private String databaseName; |
||||
|
||||
private TestDataSourceConfigurer dataSourceConfigurer; |
||||
|
||||
private TestDatabasePopulator databasePopulator; |
||||
|
||||
private DataSource dataSource; |
||||
|
||||
/** |
||||
* Creates a new TestDataSourceFactory that uses the default {@link ResourceTestDatabasePopulator}. |
||||
*/ |
||||
public TestDataSourceFactory() { |
||||
setDatabaseName("testdb"); |
||||
setDatabaseType(TestDatabaseType.HSQL); |
||||
setDatabasePopulator(new ResourceTestDatabasePopulator()); |
||||
} |
||||
|
||||
/** |
||||
* Sets the name of the test database. |
||||
* Defaults to 'testdb'. |
||||
* @param name of the test database |
||||
*/ |
||||
public void setDatabaseName(String name) { |
||||
Assert.notNull(name, "The testDatabaseName is required"); |
||||
databaseName = name; |
||||
} |
||||
|
||||
/** |
||||
* Sets the type of test database to use. |
||||
* Defaults to HSQL. |
||||
* @param type the test database type |
||||
*/ |
||||
public void setDatabaseType(TestDatabaseType type) { |
||||
Assert.notNull(type, "The TestDatabaseType is required"); |
||||
dataSourceConfigurer = TestDataSourceConfigurerFactory.getConfigurer(type); |
||||
} |
||||
|
||||
/** |
||||
* Sets the helper that will be invoked to populate the test database with data. |
||||
* Defaults a {@link ResourceTestDatabasePopulator}. |
||||
* @param populator |
||||
*/ |
||||
public void setDatabasePopulator(TestDatabasePopulator populator) { |
||||
Assert.notNull(populator, "The TestDatabasePopulator is required"); |
||||
databasePopulator = populator; |
||||
} |
||||
|
||||
// other public methods
|
||||
|
||||
/** |
||||
* The factory method that returns the {@link DataSource} that connects to the test database. |
||||
*/ |
||||
public DataSource getDataSource() { |
||||
if (dataSource == null) { |
||||
initDataSource(); |
||||
} |
||||
return dataSource; |
||||
} |
||||
|
||||
/** |
||||
* Destroy the test database. |
||||
* Does nothing if the database has not been initialized. |
||||
*/ |
||||
public void destroyDataSource() { |
||||
if (dataSource != null) { |
||||
dataSourceConfigurer.shutdown(dataSource); |
||||
dataSource = null; |
||||
} |
||||
} |
||||
|
||||
// internal helper methods
|
||||
|
||||
// encapsulates the steps involved in initializing the data source: creating it, and populating it
|
||||
private void initDataSource() { |
||||
// create the in-memory database source first
|
||||
dataSource = createDataSource(); |
||||
if (logger.isInfoEnabled()) { |
||||
logger.info("Created in-memory test database '" + databaseName + "'"); |
||||
} |
||||
if (databasePopulator != null) { |
||||
// now populate the database
|
||||
populateDatabase(); |
||||
} |
||||
} |
||||
|
||||
protected DataSource createDataSource() { |
||||
SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); |
||||
dataSourceConfigurer.configureConnectionProperties(dataSource, databaseName); |
||||
return dataSource; |
||||
} |
||||
|
||||
private void populateDatabase() { |
||||
TransactionTemplate template = new TransactionTemplate(new DataSourceTransactionManager(dataSource)); |
||||
template.execute(new TransactionCallbackWithoutResult() { |
||||
@Override |
||||
protected void doInTransactionWithoutResult(TransactionStatus status) { |
||||
databasePopulator.populate(new JdbcTemplate(dataSource)); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
||||
/** |
||||
* Strategy for populating a test database with test data. |
||||
* |
||||
* @see ResourceTestDatabasePopulator |
||||
*/ |
||||
public interface TestDatabasePopulator { |
||||
|
||||
/** |
||||
* Populate the test database using the JDBC-based data access template provided. |
||||
* @param template the data access template to use to populate the db; already configured and ready to use |
||||
* @throws DataAccessException if an unrecoverable data access exception occurs during database population |
||||
*/ |
||||
void populate(JdbcTemplate template); |
||||
} |
||||
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
/* |
||||
* Copyright 2002-2009 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.jdbc; |
||||
|
||||
/** |
||||
* A supported test database type. |
||||
* @author Keith Donald |
||||
*/ |
||||
public enum TestDatabaseType { |
||||
HSQL; |
||||
} |
||||
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
package org.springframework.test.jdbc; |
||||
|
||||
import static org.junit.Assert.assertTrue; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.dao.DataAccessException; |
||||
import org.springframework.jdbc.core.JdbcTemplate; |
||||
|
||||
public class TestDataSourceFactoryTests { |
||||
TestDataSourceFactory factory = new TestDataSourceFactory(); |
||||
|
||||
@Test |
||||
public void testGetDataSource() { |
||||
StubTestDataSourcePopulator populator = new StubTestDataSourcePopulator(); |
||||
factory.setDatabasePopulator(populator); |
||||
factory.getDataSource(); |
||||
assertTrue(populator.populateCalled); |
||||
factory.destroyDataSource(); |
||||
} |
||||
|
||||
private static class StubTestDataSourcePopulator implements TestDatabasePopulator { |
||||
|
||||
private boolean populateCalled; |
||||
|
||||
public void populate(JdbcTemplate template) throws DataAccessException { |
||||
this.populateCalled = true; |
||||
} |
||||
|
||||
} |
||||
} |
||||
Loading…
Reference in new issue