From ea9927f2a3932d5477973d106e53edd7c537a3da Mon Sep 17 00:00:00 2001 From: cachavezley Date: Wed, 5 Jun 2013 17:54:47 +0200 Subject: [PATCH 1/3] The ExpectedDatabase annotation now contains an attribute called "replaceSequenceIds" which, if true, is used the calculate the sequence values in an expected DataSet which looks like this @see http://dbunit.wikidot.com/dbunitsupport --- .../github/springtestdbunit/DbUnitRunner.java | 131 +++++++++++++++++- .../annotation/ExpectedDatabase.java | 23 +++ 2 files changed, 147 insertions(+), 7 deletions(-) diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java index bbe15c30..2aec2561 100644 --- a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java @@ -16,10 +16,8 @@ package com.github.springtestdbunit; import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.sql.ResultSet; +import java.sql.Statement; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -106,7 +104,7 @@ private void verifyExpected(DbUnitTestContext testContext, Collection> sequences = new HashMap>(); + + // We iterate on the lines and columns + for (int i = 0; i < table.getRowCount(); i++) { + for (Column column : cols) { + + // We verify that the value is not null + Object o = table.getValue(i, column.getColumnName()); + if (o != null) { + + // We look for the expression "${...}" in the value + String value = o.toString(); + if (value.startsWith("${") && value.endsWith("}")) { + + // We retrieve the sequence name + String key = value.substring(2, value.length() - 1); + + // if the map does not contain the list corresponding to the key we create it + if (sequences.containsKey(key) == false) { + sequences.put(key, new ArrayList()); + } + + // we stock the data of the element we just found + List liste = sequences.get(key); + TableValue e = new TableValue(i, column.getColumnName()); + liste.add(e); + } + } + } + } + + // we iterate the sequence names and we replace them in the dataset with the index + // that it should have according to number of times we found it in the dataset + for (String seq : sequences.keySet()) { + List liste = sequences.get(seq); + long nextVal = getNextSequenceValue(seq, databaseConnection); + long idValue = nextVal - liste.size(); + + for (TableValue e : liste) { + DefaultTable dt = (DefaultTable) table; + dt.setValue(e.getRow(), e.getColumnName(), idValue); + idValue++; + } + } + } + } + + /** + * Retrieves the next value in a SQL Sequence. + * + * @param sequenceName + * @param databaseConnection + * @return + * @throws Exception + */ + private long getNextSequenceValue(String sequenceName, IDatabaseConnection databaseConnection) throws Exception { + Statement st = databaseConnection.getConnection().createStatement(); + ResultSet rs = st.executeQuery("SELECT " + sequenceName + ".nextval FROM dual"); + rs.next(); + return rs.getLong(1); + } + private void setupOrTeardown(DbUnitTestContext testContext, boolean isSetup, Collection annotations) throws Exception { IDatabaseConnection connection = testContext.getConnection(); @@ -191,4 +279,33 @@ public static Collection get(Collec return annotationAttributes; } } + + /** + * Utility class to stock the row and columnName of the elements in the DataSet in which there is an + * Oracle Sequence to replace. + * + * @author cachavezley + */ + private class TableValue { + private final int row; + private final String columnName; + + private TableValue(int row, String columnName) { + this.row = row; + this.columnName = columnName; + } + + private int getRow() { + return this.row; + } + + private String getColumnName() { + return this.columnName; + } + + @Override + public String toString() { + return "TableValue [row=" + this.row + ", columnName=" + this.columnName + "]"; + } + } } diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/ExpectedDatabase.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/ExpectedDatabase.java index 2798c417..0e876235 100644 --- a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/ExpectedDatabase.java +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/ExpectedDatabase.java @@ -51,4 +51,27 @@ * @return Database assertion mode to use. */ DatabaseAssertionMode assertionMode() default DatabaseAssertionMode.DEFAULT; + + /** + * Flag used to indicate that we want to change the sequence names in an XML file for their values in the database. + *

+ * + * This allows us to use, for example, an xml file for the dataset that looks like this :
+ * + * + * + * + * + * + * + * + * + * The {@link org.dbunit.dataset.IDataSet} however will contain the real ids. Each sequence in the database is only accessed once (to + * know its current value), and the rest of the values are calculated based on that value and the number of times + * the sequence name is declared in the xml file. + * + * @return true if we want to change the sequence names for their values in the database, + * false otherwise + */ + boolean replaceSequenceIds() default false; } From eb0fe4e55cd7ad3d7c709798febf2252bbf96fde Mon Sep 17 00:00:00 2001 From: cachavezley Date: Wed, 5 Jun 2013 18:12:34 +0200 Subject: [PATCH 2/3] The ExpectedDatabase annotation now contains an attribute called "replaceSequenceIds" which, if true, is used the calculate the sequence values in an expected DataSet which looks like this @see http://dbunit.wikidot.com/dbunitsupport --- .../github/springtestdbunit/DbUnitRunner.java | 248 +++++++++--------- 1 file changed, 129 insertions(+), 119 deletions(-) diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java index 2aec2561..77f057df 100644 --- a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitRunner.java @@ -18,11 +18,20 @@ import java.lang.annotation.Annotation; import java.sql.ResultSet; import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dbunit.database.IDatabaseConnection; +import org.dbunit.dataset.Column; +import org.dbunit.dataset.DefaultTable; import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.ITableIterator; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -35,8 +44,8 @@ import com.github.springtestdbunit.dataset.DataSetLoader; /** - * Internal delegate class used to run tests with support for {@link DatabaseSetup @DatabaseSetup}, - * {@link DatabaseTearDown @DatabaseTearDown} and {@link ExpectedDatabase @ExpectedDatabase} annotations. + * Internal delegate class used to run tests with support for {@link com.github.springtestdbunit.annotation.DatabaseSetup @DatabaseSetup}, + * {@link com.github.springtestdbunit.annotation.DatabaseTearDown @DatabaseTearDown} and {@link com.github.springtestdbunit.annotation.ExpectedDatabase @ExpectedDatabase} annotations. * * @author Phillip Webb * @author Mario Zagar @@ -115,106 +124,107 @@ private void verifyExpected(DbUnitTestContext testContext, Collection> sequences = new HashMap>(); - - // We iterate on the lines and columns - for (int i = 0; i < table.getRowCount(); i++) { - for (Column column : cols) { - - // We verify that the value is not null - Object o = table.getValue(i, column.getColumnName()); - if (o != null) { - - // We look for the expression "${...}" in the value - String value = o.toString(); - if (value.startsWith("${") && value.endsWith("}")) { - - // We retrieve the sequence name - String key = value.substring(2, value.length() - 1); - - // if the map does not contain the list corresponding to the key we create it - if (sequences.containsKey(key) == false) { - sequences.put(key, new ArrayList()); - } - - // we stock the data of the element we just found - List liste = sequences.get(key); - TableValue e = new TableValue(i, column.getColumnName()); - liste.add(e); - } - } - } - } - - // we iterate the sequence names and we replace them in the dataset with the index - // that it should have according to number of times we found it in the dataset - for (String seq : sequences.keySet()) { - List liste = sequences.get(seq); - long nextVal = getNextSequenceValue(seq, databaseConnection); - long idValue = nextVal - liste.size(); - - for (TableValue e : liste) { - DefaultTable dt = (DefaultTable) table; - dt.setValue(e.getRow(), e.getColumnName(), idValue); - idValue++; - } - } - } - } - - /** - * Retrieves the next value in a SQL Sequence. - * - * @param sequenceName - * @param databaseConnection - * @return - * @throws Exception - */ - private long getNextSequenceValue(String sequenceName, IDatabaseConnection databaseConnection) throws Exception { - Statement st = databaseConnection.getConnection().createStatement(); - ResultSet rs = st.executeQuery("SELECT " + sequenceName + ".nextval FROM dual"); - rs.next(); - return rs.getLong(1); - } + private IDataSet loadDataset(DbUnitTestContext testContext, String dataSetLocation) throws Exception { + return loadDataset(testContext, dataSetLocation, false); + } + + /** + * Replaces the sequences names with the sequences values in a DataSet containing the expression "${...}" as a value + * name. + * @see com.github.springtestdbunit.annotation.ExpectedDatabase#replaceSequenceIds() + * + * @param dataSet the dataSet in which we will replace the sequences values. + * @param databaseConnection the connection to the database needed to query the sequences values. + * @throws Exception + */ + private void replaceSequences(IDataSet dataSet, IDatabaseConnection databaseConnection) throws Exception { + ITableIterator iter = dataSet.iterator(); + + // We iterate on the table names + while (iter.next()) { + ITable table = iter.getTable(); + Column[] cols = table.getTableMetaData().getColumns(); + + // We use this Map the count the number of times a sequence name is used in order to retroactively assign + // an ID based on the sequence value. + Map> sequences = new HashMap>(); + + // We iterate on the lines and columns + for (int i = 0; i < table.getRowCount(); i++) { + for (Column column : cols) { + + // We verify that the value is not null + Object o = table.getValue(i, column.getColumnName()); + if (o != null) { + + // We look for the expression "${...}" in the value + String value = o.toString(); + if (value.startsWith("${") && value.endsWith("}")) { + + // We retrieve the sequence name + String key = value.substring(2, value.length() - 1); + + // if the map does not contain the list corresponding to the key we create it + if (sequences.containsKey(key) == false) { + sequences.put(key, new ArrayList()); + } + + // we stock the data of the element we just found + List liste = sequences.get(key); + TableValue e = new TableValue(i, column.getColumnName()); + liste.add(e); + } + } + } + } + + // we iterate the sequence names and we replace them in the dataset with the index + // that it should have according to number of times we found it in the dataset + for (String seq : sequences.keySet()) { + List liste = sequences.get(seq); + long nextVal = getNextSequenceValue(seq, databaseConnection); + long idValue = nextVal - liste.size(); + + for (TableValue e : liste) { + DefaultTable dt = (DefaultTable) table; + dt.setValue(e.getRow(), e.getColumnName(), idValue); + idValue++; + } + } + } + } + + /** + * Retrieves the next value in a SQL Sequence. + * + * @param sequenceName + * @param databaseConnection + * @return + * @throws Exception + */ + private long getNextSequenceValue(String sequenceName, IDatabaseConnection databaseConnection) throws Exception { + Statement st = databaseConnection.getConnection().createStatement(); + ResultSet rs = st.executeQuery("SELECT " + sequenceName + ".nextval FROM dual"); + rs.next(); + return rs.getLong(1); + } private void setupOrTeardown(DbUnitTestContext testContext, boolean isSetup, Collection annotations) throws Exception { @@ -280,32 +290,32 @@ public static Collection get(Collec } } - /** - * Utility class to stock the row and columnName of the elements in the DataSet in which there is an - * Oracle Sequence to replace. - * - * @author cachavezley - */ - private class TableValue { - private final int row; - private final String columnName; - - private TableValue(int row, String columnName) { - this.row = row; - this.columnName = columnName; - } - - private int getRow() { - return this.row; - } - - private String getColumnName() { - return this.columnName; - } - - @Override - public String toString() { - return "TableValue [row=" + this.row + ", columnName=" + this.columnName + "]"; - } - } + /** + * Utility class to stock the row and columnName of the elements in the DataSet in which there is an Oracle Sequence + * to replace. + * + * @author cachavezley + */ + private class TableValue { + private final int row; + private final String columnName; + + private TableValue(int row, String columnName) { + this.row = row; + this.columnName = columnName; + } + + private int getRow() { + return this.row; + } + + private String getColumnName() { + return this.columnName; + } + + @Override + public String toString() { + return "TableValue [row=" + this.row + ", columnName=" + this.columnName + "]"; + } + } } From b5cf176ad52cb3de938a93148776cdd6465df68b Mon Sep 17 00:00:00 2001 From: cachavezley Date: Thu, 6 Jun 2013 11:10:41 +0200 Subject: [PATCH 3/3] Updated the dependency version to spring-test-dbunit-1.0.2-SNAPSHOT --- spring-test-dbunit-sample/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-test-dbunit-sample/pom.xml b/spring-test-dbunit-sample/pom.xml index 46336c7a..d9c363bf 100644 --- a/spring-test-dbunit-sample/pom.xml +++ b/spring-test-dbunit-sample/pom.xml @@ -92,7 +92,7 @@ com.github.springtestdbunit spring-test-dbunit - 1.0.1-SNAPSHOT + 1.0.2-SNAPSHOT test