Browse Source
Prior to this commit, @Sql provided attributes for configuring the syntax of the referenced SQL scripts as well as exception handling and transaction behavior; however, such configuration could not be reused across @Sql declarations thus requiring developers to copy-and-paste common configuration and resulting in unnecessary code duplication. This commit addresses this issue by introducing a new @SqlConfig annotation that can be used to declare common, global configuration for SQL scripts that can be reused within a test class hierarchy. - Introduced top-level @SqlConfig annotation and extracted common configuration attributes from @Sql. - @SqlConfig can be used at the class level for common, global config or via the new 'config' attribute of @Sql for local config. - Introduced MergedSqlConfig as a holder for the merged values from local and global @SqlConfig instances. MergedSqlConfig also contains the logic for overriding global configuration with local configuration. - Refactored all attributes of @SqlConfig to be either of type String or custom enums in order to support overriding. Empty Strings or DEFAULT enum values imply the use of a default or inherited value. Issue: SPR-11896pull/595/head
11 changed files with 770 additions and 143 deletions
@ -0,0 +1,232 @@
@@ -0,0 +1,232 @@
|
||||
/* |
||||
* Copyright 2002-2014 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.context.jdbc; |
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils; |
||||
import org.springframework.core.annotation.AnnotationAttributes; |
||||
import org.springframework.core.annotation.AnnotationUtils; |
||||
import org.springframework.core.style.ToStringCreator; |
||||
import org.springframework.jdbc.datasource.init.ScriptUtils; |
||||
import org.springframework.test.context.jdbc.SqlConfig.ErrorMode; |
||||
import org.springframework.test.context.jdbc.SqlConfig.TransactionMode; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* {@code MergedSqlConfig} encapsulates the <em>merged</em> SQL script configuration |
||||
* declared via {@link SqlConfig @SqlConfig} on a test method and its enclosing |
||||
* test class. |
||||
* <p>Explicit method-level configuration overrides class-level configuration. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 4.1 |
||||
* @see SqlConfig |
||||
*/ |
||||
class MergedSqlConfig { |
||||
|
||||
private final String dataSource; |
||||
|
||||
private final String transactionManager; |
||||
|
||||
private final TransactionMode transactionMode; |
||||
|
||||
private final String encoding; |
||||
|
||||
private final String separator; |
||||
|
||||
private final String commentPrefix; |
||||
|
||||
private final String blockCommentStartDelimiter; |
||||
|
||||
private final String blockCommentEndDelimiter; |
||||
|
||||
private final ErrorMode errorMode; |
||||
|
||||
|
||||
private static TransactionMode retrieveTransactionMode(AnnotationAttributes attributes) { |
||||
TransactionMode transactionMode = attributes.getEnum("transactionMode"); |
||||
if (transactionMode == TransactionMode.DEFAULT) { |
||||
transactionMode = TransactionMode.INFERRED; |
||||
} |
||||
return transactionMode; |
||||
} |
||||
|
||||
private static ErrorMode retrieveErrorMode(AnnotationAttributes attributes) { |
||||
ErrorMode errorMode = attributes.getEnum("errorMode"); |
||||
if (errorMode == ErrorMode.DEFAULT) { |
||||
errorMode = ErrorMode.FAIL_ON_ERROR; |
||||
} |
||||
return errorMode; |
||||
} |
||||
|
||||
private static String retrieveSeparator(AnnotationAttributes attributes) { |
||||
String separator = attributes.getString("separator"); |
||||
if (separator != null && separator.equals("")) { |
||||
separator = ScriptUtils.DEFAULT_STATEMENT_SEPARATOR; |
||||
} |
||||
return separator; |
||||
} |
||||
|
||||
private static String retrieveCommentPrefix(AnnotationAttributes attributes) { |
||||
String commentPrefix = attributes.getString("commentPrefix"); |
||||
if (commentPrefix != null && commentPrefix.equals("")) { |
||||
commentPrefix = ScriptUtils.DEFAULT_COMMENT_PREFIX; |
||||
} |
||||
return commentPrefix; |
||||
} |
||||
|
||||
private static String retrieveBlockCommentStartDelimiter(AnnotationAttributes attributes) { |
||||
String blockCommentStartDelimiter = attributes.getString("blockCommentStartDelimiter"); |
||||
if (blockCommentStartDelimiter != null && blockCommentStartDelimiter.equals("")) { |
||||
blockCommentStartDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER; |
||||
} |
||||
return blockCommentStartDelimiter; |
||||
} |
||||
|
||||
private static String retrieveBlockCommentEndDelimiter(AnnotationAttributes attributes) { |
||||
String blockCommentEndDelimiter = attributes.getString("blockCommentEndDelimiter"); |
||||
if (blockCommentEndDelimiter != null && blockCommentEndDelimiter.equals("")) { |
||||
blockCommentEndDelimiter = ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER; |
||||
} |
||||
return blockCommentEndDelimiter; |
||||
} |
||||
|
||||
/** |
||||
* Construct a {@code MergedSqlConfig} instance by merging the configuration |
||||
* from the supplied local (potentially method-level) {@code @SqlConfig} annotation |
||||
* with class-level configuration discovered on the supplied {@code testClass}. |
||||
* <p>Local configuration overrides class-level configuration. |
||||
* <p>If the test class is not annotated with {@code @SqlConfig}, no merging |
||||
* takes place and the local configuration is used "as is". |
||||
*/ |
||||
MergedSqlConfig(SqlConfig localSqlConfig, Class<?> testClass) { |
||||
Assert.notNull(localSqlConfig, "Local @SqlConfig must not be null"); |
||||
Assert.notNull(testClass, "testClass must not be null"); |
||||
|
||||
// Get global attributes, if any.
|
||||
AnnotationAttributes attributes = AnnotatedElementUtils.getAnnotationAttributes(testClass, |
||||
SqlConfig.class.getName()); |
||||
|
||||
// Override global attributes with local attributes.
|
||||
if (attributes != null) { |
||||
for (String key : attributes.keySet()) { |
||||
Object value = AnnotationUtils.getValue(localSqlConfig, key); |
||||
if (value != null) { |
||||
// Is the value explicit (i.e., not a 'default')?
|
||||
if (!value.equals("") && (value != TransactionMode.DEFAULT) && (value != ErrorMode.DEFAULT)) { |
||||
attributes.put(key, value); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
else { |
||||
// Otherwise, use local attributes only.
|
||||
attributes = AnnotationUtils.getAnnotationAttributes(localSqlConfig, false, false); |
||||
} |
||||
|
||||
this.dataSource = attributes.getString("dataSource"); |
||||
this.transactionManager = attributes.getString("transactionManager"); |
||||
this.transactionMode = retrieveTransactionMode(attributes); |
||||
this.encoding = attributes.getString("encoding"); |
||||
this.separator = retrieveSeparator(attributes); |
||||
this.commentPrefix = retrieveCommentPrefix(attributes); |
||||
this.blockCommentStartDelimiter = retrieveBlockCommentStartDelimiter(attributes); |
||||
this.blockCommentEndDelimiter = retrieveBlockCommentEndDelimiter(attributes); |
||||
this.errorMode = retrieveErrorMode(attributes); |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#dataSource() |
||||
*/ |
||||
String getDataSource() { |
||||
return this.dataSource; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#transactionManager() |
||||
*/ |
||||
String getTransactionManager() { |
||||
return this.transactionManager; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#transactionMode() |
||||
*/ |
||||
TransactionMode getTransactionMode() { |
||||
return this.transactionMode; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#encoding() |
||||
*/ |
||||
String getEncoding() { |
||||
return this.encoding; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#separator() |
||||
*/ |
||||
String getSeparator() { |
||||
return this.separator; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#commentPrefix() |
||||
*/ |
||||
String getCommentPrefix() { |
||||
return this.commentPrefix; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#blockCommentStartDelimiter() |
||||
*/ |
||||
String getBlockCommentStartDelimiter() { |
||||
return this.blockCommentStartDelimiter; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#blockCommentEndDelimiter() |
||||
*/ |
||||
String getBlockCommentEndDelimiter() { |
||||
return this.blockCommentEndDelimiter; |
||||
} |
||||
|
||||
/** |
||||
* @see SqlConfig#errorMode() |
||||
*/ |
||||
ErrorMode getErrorMode() { |
||||
return this.errorMode; |
||||
} |
||||
|
||||
/** |
||||
* Provide a String representation of the merged SQL script configuration. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new ToStringCreator(this)//
|
||||
.append("dataSource", dataSource)//
|
||||
.append("transactionManager", transactionManager)//
|
||||
.append("transactionMode", transactionMode)//
|
||||
.append("encoding", encoding)//
|
||||
.append("separator", separator)//
|
||||
.append("commentPrefix", commentPrefix)//
|
||||
.append("blockCommentStartDelimiter", blockCommentStartDelimiter)//
|
||||
.append("blockCommentEndDelimiter", blockCommentEndDelimiter)//
|
||||
.append("errorMode", errorMode)//
|
||||
.toString(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,263 @@
@@ -0,0 +1,263 @@
|
||||
/* |
||||
* Copyright 2002-2014 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.context.jdbc; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.Inherited; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.springframework.jdbc.datasource.init.ScriptUtils; |
||||
|
||||
import static java.lang.annotation.ElementType.*; |
||||
import static java.lang.annotation.RetentionPolicy.*; |
||||
|
||||
/** |
||||
* {@code @SqlConfig} defines metadata that is used to determine how to parse |
||||
* and execute SQL scripts configured via the {@link Sql @Sql} annotation. |
||||
* |
||||
* <h3>Configuration Scope</h3> |
||||
* <p>When declared as a class-level annotation on an integration test class, |
||||
* {@code @SqlConfig} serves as <strong><em>global</em></strong> configuration |
||||
* for all SQL scripts within the test class hierarchy. When declared directly |
||||
* via the {@link Sql#config config} attribute of the {@code @Sql} annotation, |
||||
* {@code @SqlConfig} serves as <strong><em>local</em></strong> configuration |
||||
* for the SQL scripts declared within the enclosing {@code @Sql} annotation. |
||||
* |
||||
* <h3>Default Values</h3> |
||||
* <p>Every attribute in {@code @SqlConfig} has an <em>implicit</em> default value |
||||
* which is documented in the javadocs of the corresponding attribute. Due to the |
||||
* rules defined for annotation attributes in the Java Language Specification, it |
||||
* is unfortunately not possible to assign a value of {@code null} to an annotation |
||||
* attribute. Thus, in order to support overrides of <em>inherited</em> global |
||||
* configuration, {@code @SqlConfig} attributes have an <em>explicit</em> |
||||
* {@code default} value of either {@code ""} for Strings or {@code DEFAULT} for |
||||
* Enums. This approach allows local declarations {@code @SqlConfig} to |
||||
* selectively override individual attributes from global declarations of |
||||
* {@code @SqlConfig} by providing a value other than {@code ""} or {@code DEFAULT}. |
||||
* |
||||
* <h3>Inheritance and Overrides</h3> |
||||
* <p>Global {@code @SqlConfig} attributes are <em>inherited</em> whenever local |
||||
* {@code @SqlConfig} attributes do not supply an explicit value other than |
||||
* {@code ""} or {@code DEFAULT}. Explicit local configuration therefore |
||||
* <em>overrides</em> global configuration. |
||||
* |
||||
* @author Sam Brannen |
||||
* @author Tadaya Tsuyukubo |
||||
* @since 4.1 |
||||
* @see Sql |
||||
*/ |
||||
@Documented |
||||
@Inherited |
||||
@Retention(RUNTIME) |
||||
@Target(TYPE) |
||||
public @interface SqlConfig { |
||||
|
||||
/** |
||||
* Enumeration of <em>modes</em> that dictate whether SQL scripts should be |
||||
* executed within a transaction and what the transaction propagation behavior |
||||
* should be. |
||||
*/ |
||||
static enum TransactionMode { |
||||
|
||||
/** |
||||
* Indicates that the <em>default</em> transaction mode should be used. |
||||
* <p>The meaning of <em>default</em> depends on the context in which |
||||
* {@code @SqlConfig} is declared: |
||||
* <ul> |
||||
* <li>If {@code @SqlConfig} is declared <strong>only</strong> locally, |
||||
* the default transaction mode is {@link #INFERRED}.</li> |
||||
* <li>If {@code @SqlConfig} is declared globally, the default transaction |
||||
* mode is {@link #INFERRED}.</li> |
||||
* <li>If {@code @SqlConfig} is declared globally <strong>and</strong> |
||||
* locally, the default transaction mode for the local declaration is |
||||
* inherited from the global declaration.</li> |
||||
* </ul> |
||||
*/ |
||||
DEFAULT, |
||||
|
||||
/** |
||||
* Indicates that the transaction mode to use when executing SQL scripts |
||||
* should be <em>inferred</em> based on whether or not a Spring-managed |
||||
* transaction is currently present. |
||||
* <p>SQL scripts will be executed within the current transaction if present; |
||||
* otherwise, scripts will be executed in a new transaction that will be |
||||
* immediately committed. |
||||
* <p>The <em>current</em> transaction will typically be managed by the |
||||
* {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener |
||||
* TransactionalTestExecutionListener}. |
||||
* @see #ISOLATED |
||||
*/ |
||||
INFERRED, |
||||
|
||||
/** |
||||
* Indicates that SQL scripts should always be executed in a new, |
||||
* <em>isolated</em> transaction that will be immediately committed. |
||||
*/ |
||||
ISOLATED |
||||
} |
||||
|
||||
/** |
||||
* Enumeration of <em>modes</em> that dictate how errors are handled while |
||||
* executing SQL statements. |
||||
*/ |
||||
static enum ErrorMode { |
||||
|
||||
/** |
||||
* Indicates that the <em>default</em> error mode should be used. |
||||
* <p>The meaning of <em>default</em> depends on the context in which |
||||
* {@code @SqlConfig} is declared: |
||||
* <ul> |
||||
* <li>If {@code @SqlConfig} is declared <strong>only</strong> locally, |
||||
* the default error mode is {@link #FAIL_ON_ERROR}.</li> |
||||
* <li>If {@code @SqlConfig} is declared globally, the default error |
||||
* mode is {@link #FAIL_ON_ERROR}.</li> |
||||
* <li>If {@code @SqlConfig} is declared globally <strong>and</strong> |
||||
* locally, the default error mode for the local declaration is |
||||
* inherited from the global declaration.</li> |
||||
* </ul> |
||||
*/ |
||||
DEFAULT, |
||||
|
||||
/** |
||||
* Indicates that script execution will fail if an error is encountered. |
||||
* In other words, no errors should be ignored. |
||||
* <p>This is effectively the default error mode so that if a script |
||||
* is accidentally executed, it will fail fast if any SQL statement in |
||||
* the script results in an error. |
||||
* @see #CONTINUE_ON_ERROR |
||||
*/ |
||||
FAIL_ON_ERROR, |
||||
|
||||
/** |
||||
* Indicates that all errors in SQL scripts should be logged but not |
||||
* propagated as exceptions. |
||||
* <p>{@code CONTINUE_ON_ERROR} is the logical <em>opposite</em> of |
||||
* {@code FAIL_ON_ERROR} and a <em>superset</em> of {@code IGNORE_FAILED_DROPS}. |
||||
* @see #FAIL_ON_ERROR |
||||
* @see #IGNORE_FAILED_DROPS |
||||
*/ |
||||
CONTINUE_ON_ERROR, |
||||
|
||||
/** |
||||
* Indicates that failed SQL {@code DROP} statements can be ignored. |
||||
* <p>This is useful for a non-embedded database whose SQL dialect does |
||||
* not support an {@code IF EXISTS} clause in a {@code DROP} statement. |
||||
* @see #CONTINUE_ON_ERROR |
||||
*/ |
||||
IGNORE_FAILED_DROPS |
||||
} |
||||
|
||||
|
||||
/** |
||||
* The bean name of the {@link javax.sql.DataSource} against which the scripts |
||||
* should be executed. |
||||
* <p>The name is only used if there is more than one bean of type |
||||
* {@code DataSource} in the test's {@code ApplicationContext}. If there is |
||||
* only one such bean, it is not necessary to specify a bean name. |
||||
* <p>Defaults to an empty string, requiring that one of the following is |
||||
* true: |
||||
* <ol> |
||||
* <li>There is only one bean of type {@code DataSource} in the test's |
||||
* {@code ApplicationContext}.</li> |
||||
* <li>The {@code DataSource} to use is named {@code "dataSource"}.</li> |
||||
* </ol> |
||||
*/ |
||||
String dataSource() default ""; |
||||
|
||||
/** |
||||
* The bean name of the {@link org.springframework.transaction.PlatformTransactionManager |
||||
* PlatformTransactionManager} that should be used to drive transactions. |
||||
* <p>The name is only used if there is more than one bean of type |
||||
* {@code PlatformTransactionManager} in the test's {@code ApplicationContext}. |
||||
* If there is only one such bean, it is not necessary to specify a bean name. |
||||
* <p>Defaults to an empty string, requiring that one of the following is |
||||
* true: |
||||
* <ol> |
||||
* <li>There is only one bean of type {@code PlatformTransactionManager} in |
||||
* the test's {@code ApplicationContext}.</li> |
||||
* <li>{@link org.springframework.transaction.annotation.TransactionManagementConfigurer |
||||
* TransactionManagementConfigurer} has been implemented to specify which |
||||
* {@code PlatformTransactionManager} bean should be used for annotation-driven |
||||
* transaction management.</li> |
||||
* <li>The {@code PlatformTransactionManager} to use is named |
||||
* {@code "transactionManager"}.</li> |
||||
* </ol> |
||||
*/ |
||||
String transactionManager() default ""; |
||||
|
||||
/** |
||||
* The <em>mode</em> to use when determining whether SQL scripts should be |
||||
* executed within a transaction. |
||||
* <p>Defaults to {@link TransactionMode#DEFAULT DEFAULT}. |
||||
* <p>Can be set to {@link TransactionMode#ISOLATED} to ensure that the SQL |
||||
* scripts are executed in a new, isolated transaction that will be immediately |
||||
* committed. |
||||
* @see TransactionMode |
||||
*/ |
||||
TransactionMode transactionMode() default TransactionMode.DEFAULT; |
||||
|
||||
/** |
||||
* The encoding for the supplied SQL scripts, if different from the platform |
||||
* encoding. |
||||
* <p>An empty string denotes that the platform encoding should be used. |
||||
*/ |
||||
String encoding() default ""; |
||||
|
||||
/** |
||||
* The character string used to separate individual statements within the |
||||
* SQL scripts. |
||||
* <p>Implicitly defaults to {@code ";"} if not specified and falls back to |
||||
* {@code "\n"} as a last resort. |
||||
* <p>May be set to {@link ScriptUtils#EOF_STATEMENT_SEPARATOR} to signal |
||||
* that each script contains a single statement without a separator. |
||||
* @see ScriptUtils#DEFAULT_STATEMENT_SEPARATOR |
||||
*/ |
||||
String separator() default ""; |
||||
|
||||
/** |
||||
* The prefix that identifies single-line comments within the SQL scripts. |
||||
* <p>Implicitly defaults to {@code "--"}. |
||||
* @see ScriptUtils#DEFAULT_COMMENT_PREFIX |
||||
*/ |
||||
String commentPrefix() default ""; |
||||
|
||||
/** |
||||
* The start delimiter that identifies block comments within the SQL scripts. |
||||
* <p>Implicitly defaults to {@code "/*"}. |
||||
* @see #blockCommentEndDelimiter |
||||
* @see ScriptUtils#DEFAULT_BLOCK_COMMENT_START_DELIMITER |
||||
*/ |
||||
String blockCommentStartDelimiter() default ""; |
||||
|
||||
/** |
||||
* The end delimiter that identifies block comments within the SQL scripts. |
||||
* <p>Implicitly defaults to <code>"*/"</code>. |
||||
* @see #blockCommentStartDelimiter |
||||
* @see ScriptUtils#DEFAULT_BLOCK_COMMENT_END_DELIMITER |
||||
*/ |
||||
String blockCommentEndDelimiter() default ""; |
||||
|
||||
/** |
||||
* The <em>mode</em> to use when an error is encountered while executing an |
||||
* SQL statement. |
||||
* <p>Defaults to {@link ErrorMode#DEFAULT DEFAULT}. |
||||
* @see ErrorMode |
||||
*/ |
||||
ErrorMode errorMode() default ErrorMode.DEFAULT; |
||||
|
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
/* |
||||
* Copyright 2002-2014 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.context.jdbc; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.test.annotation.DirtiesContext; |
||||
import org.springframework.test.context.ContextConfiguration; |
||||
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
/** |
||||
* Modified copy of {@link CustomScriptSyntaxSqlScriptsTests} with |
||||
* {@link SqlConfig @SqlConfig} defined at the class level. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 4.1 |
||||
*/ |
||||
@ContextConfiguration(classes = EmptyDatabaseConfig.class) |
||||
@DirtiesContext |
||||
@SqlConfig(commentPrefix = "`", blockCommentStartDelimiter = "#$", blockCommentEndDelimiter = "$#", separator = "@@") |
||||
public class GlobalCustomScriptSyntaxSqlScriptsTests extends AbstractTransactionalJUnit4SpringContextTests { |
||||
|
||||
@Test |
||||
@Sql(scripts = "schema.sql", config = @SqlConfig(separator = ";")) |
||||
@Sql("data-add-users-with-custom-script-syntax.sql") |
||||
public void methodLevelScripts() { |
||||
assertNumUsers(3); |
||||
} |
||||
|
||||
protected void assertNumUsers(int expected) { |
||||
assertEquals("Number of rows in the 'user' table.", expected, countRowsInTable("user")); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,177 @@
@@ -0,0 +1,177 @@
|
||||
/* |
||||
* Copyright 2002-2014 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.context.jdbc; |
||||
|
||||
import java.lang.reflect.Method; |
||||
|
||||
import org.junit.Test; |
||||
|
||||
import static org.junit.Assert.*; |
||||
import static org.springframework.jdbc.datasource.init.ScriptUtils.*; |
||||
import static org.springframework.test.context.jdbc.SqlConfig.ErrorMode.*; |
||||
import static org.springframework.test.context.jdbc.SqlConfig.TransactionMode.*; |
||||
|
||||
/** |
||||
* Unit tests for {@link MergedSqlConfig}. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 4.1 |
||||
*/ |
||||
public class MergedSqlConfigTests { |
||||
|
||||
private void assertDefaults(MergedSqlConfig cfg) { |
||||
assertNotNull(cfg); |
||||
assertEquals("dataSource", "", cfg.getDataSource()); |
||||
assertEquals("transactionManager", "", cfg.getTransactionManager()); |
||||
assertEquals("transactionMode", INFERRED, cfg.getTransactionMode()); |
||||
assertEquals("encoding", "", cfg.getEncoding()); |
||||
assertEquals("separator", DEFAULT_STATEMENT_SEPARATOR, cfg.getSeparator()); |
||||
assertEquals("commentPrefix", DEFAULT_COMMENT_PREFIX, cfg.getCommentPrefix()); |
||||
assertEquals("blockCommentStartDelimiter", DEFAULT_BLOCK_COMMENT_START_DELIMITER, |
||||
cfg.getBlockCommentStartDelimiter()); |
||||
assertEquals("blockCommentEndDelimiter", DEFAULT_BLOCK_COMMENT_END_DELIMITER, cfg.getBlockCommentEndDelimiter()); |
||||
assertEquals("errorMode", FAIL_ON_ERROR, cfg.getErrorMode()); |
||||
} |
||||
|
||||
@Test |
||||
public void localConfigWithDefaults() throws Exception { |
||||
Method method = getClass().getMethod("localConfigMethodWithDefaults"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, getClass()); |
||||
assertDefaults(cfg); |
||||
} |
||||
|
||||
@Test |
||||
public void globalConfigWithDefaults() throws Exception { |
||||
Method method = GlobalConfigWithDefaultsClass.class.getMethod("globalConfigMethod"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, GlobalConfigWithDefaultsClass.class); |
||||
assertDefaults(cfg); |
||||
} |
||||
|
||||
@Test |
||||
public void localConfigWithCustomValues() throws Exception { |
||||
Method method = getClass().getMethod("localConfigMethodWithCustomValues"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, getClass()); |
||||
assertNotNull(cfg); |
||||
assertEquals("dataSource", "ds", cfg.getDataSource()); |
||||
assertEquals("transactionManager", "txMgr", cfg.getTransactionManager()); |
||||
assertEquals("transactionMode", ISOLATED, cfg.getTransactionMode()); |
||||
assertEquals("encoding", "enigma", cfg.getEncoding()); |
||||
assertEquals("separator", "\n", cfg.getSeparator()); |
||||
assertEquals("commentPrefix", "`", cfg.getCommentPrefix()); |
||||
assertEquals("blockCommentStartDelimiter", "<<", cfg.getBlockCommentStartDelimiter()); |
||||
assertEquals("blockCommentEndDelimiter", ">>", cfg.getBlockCommentEndDelimiter()); |
||||
assertEquals("errorMode", IGNORE_FAILED_DROPS, cfg.getErrorMode()); |
||||
} |
||||
|
||||
@Test |
||||
public void localConfigWithContinueOnError() throws Exception { |
||||
Method method = getClass().getMethod("localConfigMethodWithContinueOnError"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, getClass()); |
||||
assertNotNull(cfg); |
||||
assertEquals("errorMode", CONTINUE_ON_ERROR, cfg.getErrorMode()); |
||||
} |
||||
|
||||
@Test |
||||
public void localConfigWithIgnoreFailedDrops() throws Exception { |
||||
Method method = getClass().getMethod("localConfigMethodWithIgnoreFailedDrops"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, getClass()); |
||||
assertNotNull(cfg); |
||||
assertEquals("errorMode", IGNORE_FAILED_DROPS, cfg.getErrorMode()); |
||||
} |
||||
|
||||
@Test |
||||
public void globalConfig() throws Exception { |
||||
Method method = GlobalConfigClass.class.getMethod("globalConfigMethod"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, GlobalConfigClass.class); |
||||
assertNotNull(cfg); |
||||
assertEquals("dataSource", "", cfg.getDataSource()); |
||||
assertEquals("transactionManager", "", cfg.getTransactionManager()); |
||||
assertEquals("transactionMode", INFERRED, cfg.getTransactionMode()); |
||||
assertEquals("encoding", "global", cfg.getEncoding()); |
||||
assertEquals("separator", "\n", cfg.getSeparator()); |
||||
assertEquals("commentPrefix", DEFAULT_COMMENT_PREFIX, cfg.getCommentPrefix()); |
||||
assertEquals("blockCommentStartDelimiter", DEFAULT_BLOCK_COMMENT_START_DELIMITER, |
||||
cfg.getBlockCommentStartDelimiter()); |
||||
assertEquals("blockCommentEndDelimiter", DEFAULT_BLOCK_COMMENT_END_DELIMITER, cfg.getBlockCommentEndDelimiter()); |
||||
assertEquals("errorMode", IGNORE_FAILED_DROPS, cfg.getErrorMode()); |
||||
} |
||||
|
||||
@Test |
||||
public void globalConfigWithLocalOverrides() throws Exception { |
||||
Method method = GlobalConfigClass.class.getMethod("globalConfigWithLocalOverridesMethod"); |
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config(); |
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, GlobalConfigClass.class); |
||||
|
||||
assertNotNull(cfg); |
||||
assertEquals("dataSource", "", cfg.getDataSource()); |
||||
assertEquals("transactionManager", "", cfg.getTransactionManager()); |
||||
assertEquals("transactionMode", INFERRED, cfg.getTransactionMode()); |
||||
assertEquals("encoding", "local", cfg.getEncoding()); |
||||
assertEquals("separator", "@@", cfg.getSeparator()); |
||||
assertEquals("commentPrefix", DEFAULT_COMMENT_PREFIX, cfg.getCommentPrefix()); |
||||
assertEquals("blockCommentStartDelimiter", DEFAULT_BLOCK_COMMENT_START_DELIMITER, |
||||
cfg.getBlockCommentStartDelimiter()); |
||||
assertEquals("blockCommentEndDelimiter", DEFAULT_BLOCK_COMMENT_END_DELIMITER, cfg.getBlockCommentEndDelimiter()); |
||||
assertEquals("errorMode", CONTINUE_ON_ERROR, cfg.getErrorMode()); |
||||
} |
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Sql |
||||
public static void localConfigMethodWithDefaults() { |
||||
} |
||||
|
||||
@Sql(config = @SqlConfig(dataSource = "ds", transactionManager = "txMgr", transactionMode = ISOLATED, encoding = "enigma", separator = "\n", commentPrefix = "`", blockCommentStartDelimiter = "<<", blockCommentEndDelimiter = ">>", errorMode = IGNORE_FAILED_DROPS)) |
||||
public static void localConfigMethodWithCustomValues() { |
||||
} |
||||
|
||||
@Sql(config = @SqlConfig(errorMode = CONTINUE_ON_ERROR)) |
||||
public static void localConfigMethodWithContinueOnError() { |
||||
} |
||||
|
||||
@Sql(config = @SqlConfig(errorMode = IGNORE_FAILED_DROPS)) |
||||
public static void localConfigMethodWithIgnoreFailedDrops() { |
||||
} |
||||
|
||||
|
||||
@SqlConfig |
||||
public static class GlobalConfigWithDefaultsClass { |
||||
|
||||
@Sql("foo.sql") |
||||
public void globalConfigMethod() { |
||||
} |
||||
} |
||||
|
||||
@SqlConfig(encoding = "global", separator = "\n", errorMode = IGNORE_FAILED_DROPS) |
||||
public static class GlobalConfigClass { |
||||
|
||||
@Sql("foo.sql") |
||||
public void globalConfigMethod() { |
||||
} |
||||
|
||||
@Sql(scripts = "foo.sql", config = @SqlConfig(encoding = "local", separator = "@@", errorMode = CONTINUE_ON_ERROR)) |
||||
public void globalConfigWithLocalOverridesMethod() { |
||||
} |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue