From e7b3bb3c1b8685135665cbcdad8bd6d6aff611d1 Mon Sep 17 00:00:00 2001 From: Toilal Date: Thu, 25 Aug 2016 12:14:40 +0200 Subject: [PATCH] Add DatabaseAssertionLookup (equivalent of DatabaseOperationLookup for @ExpectedDatabase) --- .../github/springtestdbunit/DbUnitRunner.java | 9 ++- .../springtestdbunit/DbUnitTestContext.java | 14 +++++ .../DbUnitTestExecutionListener.java | 41 +++++++++++++ .../annotation/DbUnitConfiguration.java | 16 +++++ .../annotation/ExpectedDatabase.java | 7 +++ .../assertion/DatabaseAssertionLookup.java | 14 +++++ .../DefaultDatabaseAssertionLookup.java | 11 ++++ ...bUnitTestExecutionListenerPrepareTest.java | 28 ++++++++- .../AssertAllDatabaseAssertionLookup.java | 28 +++++++++ .../ExpectedAssertionLookupOnClassTest.java | 58 +++++++++++++++++++ .../resources/META-INF/dbunit-context.xml | 2 + 11 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DatabaseAssertionLookup.java create mode 100644 spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DefaultDatabaseAssertionLookup.java create mode 100644 spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/AssertAllDatabaseAssertionLookup.java create mode 100644 spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/ExpectedAssertionLookupOnClassTest.java 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 6d7ebed1..29fc60a8 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 @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dbunit.DatabaseUnitException; @@ -138,7 +139,13 @@ private void verifyExpected(DbUnitTestContext testContext, DatabaseConnections c if (logger.isDebugEnabled()) { logger.debug("Veriftying @DatabaseTest expectation using " + annotation.value()); } - DatabaseAssertion assertion = annotation.assertionMode().getDatabaseAssertion(); + DatabaseAssertionLookup databaseAssertionLookup; + if (StringUtils.hasLength(annotation.assertionLookup())) { + databaseAssertionLookup = testContext.getDatabaseAssertionLookup(annotation.assertionLookup()); + } else { + databaseAssertionLookup = testContext.getDatabaseAssertionLookup(); + } + DatabaseAssertion assertion = databaseAssertionLookup.getDatabaseAssertion(annotation.assertionMode()); List columnFilters = getColumnFilters(annotation); if (StringUtils.hasLength(query)) { Assert.hasLength(table, "The table name must be specified when using a SQL query"); diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestContext.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestContext.java index fca0e15f..72924fe0 100644 --- a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestContext.java +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestContext.java @@ -18,6 +18,7 @@ import java.lang.reflect.Method; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.IDataSet; @@ -43,6 +44,19 @@ public interface DbUnitTestContext { */ DataSetLoader getDataSetLoader(); + /** + * Returns the {@link DatabaseAssertionLookup} that should be used. + * @return The database assertion factory + */ + DatabaseAssertionLookup getDatabaseAssertionLookup(); + + /** + * Returns the {@link DatabaseAssertionLookup} registered with given bean name. + * @param beanName bean name of the {@link DatabaseAssertionLookup} + * @return The database assertion factory + */ + DatabaseAssertionLookup getDatabaseAssertionLookup(String beanName); + /** * Returns the {@link DatabaseOperationLookup} that should be used to lookup database operations. * @return the database operation lookup diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestExecutionListener.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestExecutionListener.java index 185974cf..e631616c 100644 --- a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestExecutionListener.java +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/DbUnitTestExecutionListener.java @@ -21,6 +21,8 @@ import javax.sql.DataSource; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; +import com.github.springtestdbunit.assertion.DefaultDatabaseAssertionLookup; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dbunit.database.IDatabaseConnection; @@ -71,12 +73,17 @@ public class DbUnitTestExecutionListener extends AbstractTestExecutionListener { private static final String DATA_SET_LOADER_BEAN_NAME = "dbUnitDataSetLoader"; + private static final String DATABASE_ASSERTION_LOOKUP_BEAN_NAME = "dbUnitDatabaseAssertionLookup"; + protected static final String CONNECTION_ATTRIBUTE = Conventions .getQualifiedAttributeName(DbUnitTestExecutionListener.class, "connection"); protected static final String DATA_SET_LOADER_ATTRIBUTE = Conventions .getQualifiedAttributeName(DbUnitTestExecutionListener.class, "dataSetLoader"); + protected static final String DATABASE_ASSERTION_LOOKUP_ATTRIBUTE = Conventions + .getQualifiedAttributeName(DbUnitTestExecutionListener.class, "databaseAssertionLookup"); + protected static final String DATABASE_OPERATION_LOOKUP_ATTRIBUTE = Conventions .getQualifiedAttributeName(DbUnitTestExecutionListener.class, "databseOperationLookup"); @@ -94,6 +101,8 @@ public void prepareTestInstance(DbUnitTestContextAdapter testContext) throws Exc String[] databaseConnectionBeanNames = null; String dataSetLoaderBeanName = null; Class dataSetLoaderClass = FlatXmlDataSetLoader.class; + String databaseAssertionLookupBeanName = null; + Class databaseAssertionLookupClass = DefaultDatabaseAssertionLookup.class; Class databaseOperationLookupClass = DefaultDatabaseOperationLookup.class; DbUnitConfiguration configuration = testContext.getTestClass().getAnnotation(DbUnitConfiguration.class); @@ -104,6 +113,8 @@ public void prepareTestInstance(DbUnitTestContextAdapter testContext) throws Exc databaseConnectionBeanNames = configuration.databaseConnection(); dataSetLoaderClass = configuration.dataSetLoader(); dataSetLoaderBeanName = configuration.dataSetLoaderBean(); + databaseAssertionLookupClass = configuration.databaseAssertionLookup(); + databaseAssertionLookupBeanName = configuration.databaseAssertionLookupBean(); databaseOperationLookupClass = configuration.databaseOperationLookup(); } @@ -118,6 +129,12 @@ public void prepareTestInstance(DbUnitTestContextAdapter testContext) throws Exc } } + if (!StringUtils.hasLength(databaseAssertionLookupBeanName)) { + if (testContext.getApplicationContext().containsBean(DATABASE_ASSERTION_LOOKUP_BEAN_NAME)) { + dataSetLoaderBeanName = DATABASE_ASSERTION_LOOKUP_BEAN_NAME; + } + } + if (logger.isDebugEnabled()) { logger.debug("DBUnit tests will run using databaseConnection \"" + StringUtils.arrayToCommaDelimitedString(databaseConnectionBeanNames) @@ -126,6 +143,7 @@ public void prepareTestInstance(DbUnitTestContextAdapter testContext) throws Exc } prepareDatabaseConnection(testContext, databaseConnectionBeanNames); prepareDataSetLoader(testContext, dataSetLoaderBeanName, dataSetLoaderClass); + prepareDatabaseAssertionsFactory(testContext, databaseAssertionLookupBeanName, databaseAssertionLookupClass); prepareDatabaseOperationLookup(testContext, databaseOperationLookupClass); } @@ -170,6 +188,21 @@ private void prepareDataSetLoader(DbUnitTestContextAdapter testContext, String b } } + private void prepareDatabaseAssertionsFactory(DbUnitTestContextAdapter testContext, String beanName, + Class databaseAssertionFactoryClass) { + if (StringUtils.hasLength(beanName)) { + testContext.setAttribute(DATABASE_ASSERTION_LOOKUP_ATTRIBUTE, + testContext.getApplicationContext().getBean(beanName, DatabaseAssertionLookup.class)); + } else { + try { + testContext.setAttribute(DATABASE_ASSERTION_LOOKUP_ATTRIBUTE, databaseAssertionFactoryClass.newInstance()); + } catch (Exception ex) { + throw new IllegalArgumentException( + "Unable to create database assertion factory instance for " + databaseAssertionFactoryClass, ex); + } + } + } + private void prepareDatabaseOperationLookup(DbUnitTestContextAdapter testContext, Class databaseOperationLookupClass) { try { @@ -232,6 +265,14 @@ public DataSetLoader getDataSetLoader() { return (DataSetLoader) getAttribute(DATA_SET_LOADER_ATTRIBUTE); } + public DatabaseAssertionLookup getDatabaseAssertionLookup() { + return (DatabaseAssertionLookup) getAttribute(DATABASE_ASSERTION_LOOKUP_ATTRIBUTE); + } + + public DatabaseAssertionLookup getDatabaseAssertionLookup(String beanName) { + return getApplicationContext().getBean(beanName, DatabaseAssertionLookup.class); + } + public DatabaseOperationLookup getDatbaseOperationLookup() { return (DatabaseOperationLookup) getAttribute(DATABASE_OPERATION_LOOKUP_ATTRIBUTE); } diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/DbUnitConfiguration.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/DbUnitConfiguration.java index c1f4a26f..068e4198 100644 --- a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/DbUnitConfiguration.java +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/annotation/DbUnitConfiguration.java @@ -25,10 +25,12 @@ import javax.sql.DataSource; +import com.github.springtestdbunit.assertion.DefaultDatabaseAssertionLookup; import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.IDataSet; import com.github.springtestdbunit.DbUnitTestExecutionListener; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; import com.github.springtestdbunit.dataset.DataSetLoader; import com.github.springtestdbunit.dataset.FlatXmlDataSetLoader; import com.github.springtestdbunit.operation.DatabaseOperationLookup; @@ -68,6 +70,20 @@ */ String dataSetLoaderBean() default ""; + /** + * Returns the class will be used for database assertion factory. The specified class must implement + * {@link DatabaseAssertionLookup} and must have a default constructor. + * @return the database assertion factory class + */ + Class databaseAssertionLookup() default DefaultDatabaseAssertionLookup.class; + + /** + * Returns the name of the bean that will be used for database assertion factory. The specified bean must + * implement {@link DatabaseAssertionLookup}. + * @return the data set loader bean name + */ + String databaseAssertionLookupBean() default ""; + /** * Returns the class that will be used to lookup DBUnit databse operations. The specific class must implement * {@link DatabaseOperationLookup} and must have a default constructor. 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 14811fce..ce7002cb 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 @@ -24,6 +24,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.filter.IColumnFilter; @@ -66,6 +67,12 @@ */ DatabaseAssertionMode assertionMode() default DatabaseAssertionMode.DEFAULT; + /** + * {@link DatabaseAssertionLookup} bean name to use. + * @return Bean name of the database assertion factory. + */ + String assertionLookup() default ""; + /** * Optional table name that can be used to limit the comparison to a specific table. * @return the table name diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DatabaseAssertionLookup.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DatabaseAssertionLookup.java new file mode 100644 index 00000000..862fdd12 --- /dev/null +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DatabaseAssertionLookup.java @@ -0,0 +1,14 @@ +package com.github.springtestdbunit.assertion; + +/** + * Strategy used to lookup {@link DatabaseAssertion} from a value {@link DatabaseAssertionMode enum value}. + */ +public interface DatabaseAssertionLookup { + /** + * Get the {@link DatabaseAssertion} implementation for this mode. + * + * @param mode Database assertion mode + * @return Database assertion + */ + DatabaseAssertion getDatabaseAssertion(DatabaseAssertionMode mode); +} diff --git a/spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DefaultDatabaseAssertionLookup.java b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DefaultDatabaseAssertionLookup.java new file mode 100644 index 00000000..6e92060d --- /dev/null +++ b/spring-test-dbunit/src/main/java/com/github/springtestdbunit/assertion/DefaultDatabaseAssertionLookup.java @@ -0,0 +1,11 @@ +package com.github.springtestdbunit.assertion; + +/** + * Default implementation for {@link DatabaseAssertionLookup}, delegating to {@link DatabaseAssertionMode#databaseAssertion} + */ +public class DefaultDatabaseAssertionLookup implements DatabaseAssertionLookup { + + public DatabaseAssertion getDatabaseAssertion(DatabaseAssertionMode mode) { + return mode.getDatabaseAssertion(); + } +} diff --git a/spring-test-dbunit/src/test/java/com/github/springtestdbunit/DbUnitTestExecutionListenerPrepareTest.java b/spring-test-dbunit/src/test/java/com/github/springtestdbunit/DbUnitTestExecutionListenerPrepareTest.java index 2114da0b..ef0497ef 100644 --- a/spring-test-dbunit/src/test/java/com/github/springtestdbunit/DbUnitTestExecutionListenerPrepareTest.java +++ b/spring-test-dbunit/src/test/java/com/github/springtestdbunit/DbUnitTestExecutionListenerPrepareTest.java @@ -23,6 +23,9 @@ import javax.sql.DataSource; +import com.github.springtestdbunit.assertion.DatabaseAssertion; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; +import com.github.springtestdbunit.assertion.DatabaseAssertionMode; import org.dbunit.database.DatabaseDataSourceConnection; import org.dbunit.database.IDatabaseConnection; import org.dbunit.dataset.IDataSet; @@ -100,6 +103,7 @@ private void testCommonBeanNames(Class testClass) throws Exception { ExtendedTestContextManager testContextManager = new ExtendedTestContextManager(testClass); testContextManager.prepareTestInstance(); verify(this.applicationContext).containsBean("dbUnitDataSetLoader"); + verify(this.applicationContext).containsBean("dbUnitDatabaseAssertionLookup"); verify(this.applicationContext).containsBean("dbUnitDatabaseConnection"); verify(this.applicationContext).containsBean("dataSource"); verify(this.applicationContext).getBean("dataSource"); @@ -139,6 +143,19 @@ public void shouldFailIfDatabaseConnectionOfWrongTypeIsFound() throws Exception } } + @Test + public void shouldFailIfDatabaseAssertionFactoryWrongTypeIsFound() throws Exception { + addBean("dataSource", this.dataSource); + addBean("dbUnitDatabaseAssertionFactory", new Integer(0)); + ExtendedTestContextManager testContextManager = new ExtendedTestContextManager(NoDbUnitConfiguration.class); + try { + testContextManager.prepareTestInstance(); + } catch (IllegalArgumentException ex) { + assertEquals("Object of class [java.lang.Integer] must be an instance of interface " + + "com.github.springtestdbunit.assertion.DatabaseAssertionFactory", ex.getMessage()); + } + } + @Test public void shouldSupportAllDbUnitConfigurationAttributes() throws Exception { addBean("customBean", this.databaseConnection); @@ -196,6 +213,12 @@ public IDataSet loadDataSet(Class testClass, String location) throws Exceptio public static class CustomDataSetLoader extends AbstractCustomDataSetLoader { } + public static class CustomDatabaseAssertionLookup implements DatabaseAssertionLookup { + public DatabaseAssertion getDatabaseAssertion(DatabaseAssertionMode mode) { + return null; + } + } + public static class CustomDatabaseOperationLookup implements DatabaseOperationLookup { public org.dbunit.operation.DatabaseOperation get(DatabaseOperation operation) { return null; @@ -217,7 +240,10 @@ private static class EmptyDbUnitConfiguration { @ContextConfiguration(loader = LocalApplicationContextLoader.class) @TestExecutionListeners(DbUnitTestExecutionListener.class) - @DbUnitConfiguration(databaseConnection = "customBean", dataSetLoader = CustomDataSetLoader.class, databaseOperationLookup = CustomDatabaseOperationLookup.class) + @DbUnitConfiguration(databaseConnection = "customBean", + dataSetLoader = CustomDataSetLoader.class, + databaseAssertionLookup = CustomDatabaseAssertionLookup.class, + databaseOperationLookup = CustomDatabaseOperationLookup.class) private static class CustomConfiguration { } diff --git a/spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/AssertAllDatabaseAssertionLookup.java b/spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/AssertAllDatabaseAssertionLookup.java new file mode 100644 index 00000000..0c35ff5b --- /dev/null +++ b/spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/AssertAllDatabaseAssertionLookup.java @@ -0,0 +1,28 @@ +package com.github.springtestdbunit.expected; + +import com.github.springtestdbunit.assertion.DatabaseAssertion; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; +import com.github.springtestdbunit.assertion.DatabaseAssertionMode; +import org.dbunit.DatabaseUnitException; +import org.dbunit.dataset.IDataSet; +import org.dbunit.dataset.ITable; +import org.dbunit.dataset.filter.IColumnFilter; + +import java.util.List; + +public class AssertAllDatabaseAssertionLookup implements DatabaseAssertionLookup { + private static class AssertAllDatabaseAssertion implements DatabaseAssertion { + @Override + public void assertEquals(IDataSet expectedDataSet, IDataSet actualDataSet, List columnFilters) throws DatabaseUnitException { + } + + @Override + public void assertEquals(ITable expectedTable, ITable actualTable, List columnFilters) throws DatabaseUnitException { + } + } + + @Override + public DatabaseAssertion getDatabaseAssertion(DatabaseAssertionMode mode) { + return new AssertAllDatabaseAssertion(); + } +} diff --git a/spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/ExpectedAssertionLookupOnClassTest.java b/spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/ExpectedAssertionLookupOnClassTest.java new file mode 100644 index 00000000..5288d307 --- /dev/null +++ b/spring-test-dbunit/src/test/java/com/github/springtestdbunit/expected/ExpectedAssertionLookupOnClassTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2016 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 com.github.springtestdbunit.expected; + +import com.github.springtestdbunit.DbUnitTestExecutionListener; +import com.github.springtestdbunit.annotation.ExpectedDatabase; +import com.github.springtestdbunit.assertion.DatabaseAssertion; +import com.github.springtestdbunit.assertion.DatabaseAssertionLookup; +import com.github.springtestdbunit.assertion.DatabaseAssertionMode; +import com.github.springtestdbunit.entity.EntityAssert; +import com.github.springtestdbunit.testutils.MustFailDbUnitTestExecutionListener; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/META-INF/dbunit-context.xml") +@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DbUnitTestExecutionListener.class }) +@ExpectedDatabase(value = "/META-INF/db/expectedfail.xml", assertionLookup = "assertAllDatabaseAssertionLookup") +@Transactional +public class ExpectedAssertionLookupOnClassTest { + static class CustomLookup implements DatabaseAssertionLookup { + + @Override + public DatabaseAssertion getDatabaseAssertion(DatabaseAssertionMode mode) { + return null; + } + } + + + @Autowired + private EntityAssert entityAssert; + + @Test + public void test() throws Exception { + this.entityAssert.assertValues("existing1", "existing2"); + } + +} diff --git a/spring-test-dbunit/src/test/resources/META-INF/dbunit-context.xml b/spring-test-dbunit/src/test/resources/META-INF/dbunit-context.xml index 5428e04b..3c63937a 100644 --- a/spring-test-dbunit/src/test/resources/META-INF/dbunit-context.xml +++ b/spring-test-dbunit/src/test/resources/META-INF/dbunit-context.xml @@ -16,6 +16,8 @@ + +