Discover @Sql annotations on enclosing class for nested test class
This commit introduces support for discovering @Sql, @SqlGroup, @SqlConfig, and @SqlMergeMode on enclosing classes for @Nested test classes in JUnit Jupiter. Closes gh-25913
This commit is contained in:
parent
95110d8257
commit
b8b854db8c
|
|
@ -78,6 +78,9 @@ import org.springframework.lang.Nullable;
|
|||
* <li>{@link org.springframework.transaction.annotation.Transactional @Transactional}</li>
|
||||
* <li>{@link org.springframework.test.annotation.Rollback @Rollback}</li>
|
||||
* <li>{@link org.springframework.test.annotation.Commit @Commit}</li>
|
||||
* <li>{@link org.springframework.test.context.jdbc.Sql @Sql}</li>
|
||||
* <li>{@link org.springframework.test.context.jdbc.SqlConfig @SqlConfig}</li>
|
||||
* <li>{@link org.springframework.test.context.jdbc.SqlMergeMode @SqlMergeMode}</li>
|
||||
* <li>{@link TestConstructor @TestConstructor}</li>
|
||||
* </ul>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package org.springframework.test.context.jdbc;
|
|||
import java.lang.reflect.Array;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
|
|
@ -27,6 +26,7 @@ import org.springframework.jdbc.datasource.init.ScriptUtils;
|
|||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.test.context.jdbc.SqlConfig.ErrorMode;
|
||||
import org.springframework.test.context.jdbc.SqlConfig.TransactionMode;
|
||||
import org.springframework.test.util.MetaAnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
|
@ -100,14 +100,15 @@ class MergedSqlConfig {
|
|||
enforceCommentPrefixAliases(localAttributes);
|
||||
|
||||
// Get global attributes, if any.
|
||||
AnnotationAttributes globalAttributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
|
||||
testClass, SqlConfig.class.getName(), false, false);
|
||||
SqlConfig globalSqlConfig = MetaAnnotationUtils.findMergedAnnotation(testClass, SqlConfig.class);
|
||||
|
||||
// Use local attributes only?
|
||||
if (globalAttributes == null) {
|
||||
if (globalSqlConfig == null) {
|
||||
return localAttributes;
|
||||
}
|
||||
|
||||
AnnotationAttributes globalAttributes = AnnotationUtils.getAnnotationAttributes(globalSqlConfig, false, false);
|
||||
|
||||
// Enforce comment prefix aliases within the global @SqlConfig.
|
||||
enforceCommentPrefixAliases(globalAttributes);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
package org.springframework.test.context.jdbc;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
|
@ -42,6 +41,7 @@ import org.springframework.test.context.jdbc.SqlMergeMode.MergeMode;
|
|||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.TestContextTransactionUtils;
|
||||
import org.springframework.test.context.util.TestContextResourceUtils;
|
||||
import org.springframework.test.util.MetaAnnotationUtils;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
|
|
@ -162,18 +162,33 @@ public class SqlScriptsTestExecutionListener extends AbstractTestExecutionListen
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the {@code @SqlMergeMode} annotation declared on the supplied {@code element}.
|
||||
* Get the {@code @SqlMergeMode} annotation declared on the supplied class.
|
||||
*/
|
||||
@Nullable
|
||||
private SqlMergeMode getSqlMergeModeFor(AnnotatedElement element) {
|
||||
return AnnotatedElementUtils.findMergedAnnotation(element, SqlMergeMode.class);
|
||||
private SqlMergeMode getSqlMergeModeFor(Class<?> clazz) {
|
||||
return MetaAnnotationUtils.findMergedAnnotation(clazz, SqlMergeMode.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code @Sql} annotations declared on the supplied {@code element}.
|
||||
* Get the {@code @SqlMergeMode} annotation declared on the supplied method.
|
||||
*/
|
||||
private Set<Sql> getSqlAnnotationsFor(AnnotatedElement element) {
|
||||
return AnnotatedElementUtils.getMergedRepeatableAnnotations(element, Sql.class, SqlGroup.class);
|
||||
@Nullable
|
||||
private SqlMergeMode getSqlMergeModeFor(Method method) {
|
||||
return AnnotatedElementUtils.findMergedAnnotation(method, SqlMergeMode.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code @Sql} annotations declared on the supplied class.
|
||||
*/
|
||||
private Set<Sql> getSqlAnnotationsFor(Class<?> clazz) {
|
||||
return MetaAnnotationUtils.getMergedRepeatableAnnotations(clazz, Sql.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code @Sql} annotations declared on the supplied method.
|
||||
*/
|
||||
private Set<Sql> getSqlAnnotationsFor(Method method) {
|
||||
return AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Sql.class, SqlGroup.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.test.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
|
@ -85,12 +86,16 @@ public abstract class MetaAnnotationUtils {
|
|||
* {@linkplain Class#getEnclosingClass() enclosing class} hierarchy of the
|
||||
* supplied class. The enclosing class hierarchy will only be searched if
|
||||
* appropriate.
|
||||
* <p>{@link org.springframework.core.annotation.AliasFor @AliasFor} semantics
|
||||
* are fully supported, both within a single annotation and within annotation
|
||||
* hierarchies.
|
||||
* @param clazz the class to look for annotations on
|
||||
* @param annotationType the type of annotation to look for
|
||||
* @return the merged, synthesized {@code Annotation}, or {@code null} if not found
|
||||
* @since 5.3
|
||||
* @see AnnotatedElementUtils#findMergedAnnotation(java.lang.reflect.AnnotatedElement, Class)
|
||||
* @see #findAnnotationDescriptor(Class, Class)
|
||||
* @see #searchEnclosingClass(Class)
|
||||
*/
|
||||
@Nullable
|
||||
public static <T extends Annotation> T findMergedAnnotation(Class<?> clazz, Class<T> annotationType) {
|
||||
|
|
@ -106,6 +111,53 @@ public abstract class MetaAnnotationUtils {
|
|||
return (descriptor != null ? descriptor.synthesizeAnnotation() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all <em>repeatable annotations</em> of the specified {@code annotationType}
|
||||
* within the annotation hierarchy <em>above</em> the supplied class; and for
|
||||
* each annotation found, merge that annotation's attributes with <em>matching</em>
|
||||
* attributes from annotations in lower levels of the annotation hierarchy and
|
||||
* synthesize the results back into an annotation of the specified {@code annotationType}.
|
||||
* <p>This method will find {@link java.lang.annotation.Inherited @Inherited}
|
||||
* annotations declared on superclasses if the supplied class does not have
|
||||
* any local declarations of the repeatable annotation. If no inherited
|
||||
* annotations are found, this method will search within the
|
||||
* {@linkplain Class#getEnclosingClass() enclosing class} hierarchy of the
|
||||
* supplied class. The enclosing class hierarchy will only be searched if
|
||||
* appropriate.
|
||||
* <p>The container type that holds the repeatable annotations will be looked up
|
||||
* via {@link java.lang.annotation.Repeatable}.
|
||||
* <p>{@link org.springframework.core.annotation.AliasFor @AliasFor} semantics
|
||||
* are fully supported, both within a single annotation and within annotation
|
||||
* hierarchies.
|
||||
* @param clazz the class on which to search for annotations (never {@code null})
|
||||
* @param annotationType the annotation type to find (never {@code null})
|
||||
* @return the set of all merged repeatable annotations found, or an empty set
|
||||
* if none were found
|
||||
* @since 5.3
|
||||
* @see AnnotatedElementUtils#getMergedRepeatableAnnotations(java.lang.reflect.AnnotatedElement, Class)
|
||||
* @see #searchEnclosingClass(Class)
|
||||
*/
|
||||
public static <T extends Annotation> Set<T> getMergedRepeatableAnnotations(
|
||||
Class<?> clazz, Class<T> annotationType) {
|
||||
|
||||
// Present (via @Inherited semantics), directly present, or meta-present?
|
||||
Set<T> mergedAnnotations = MergedAnnotations.from(clazz, SearchStrategy.INHERITED_ANNOTATIONS)
|
||||
.stream(annotationType)
|
||||
.collect(MergedAnnotationCollectors.toAnnotationSet());
|
||||
|
||||
if (!mergedAnnotations.isEmpty()) {
|
||||
return mergedAnnotations;
|
||||
}
|
||||
|
||||
// Declared on an enclosing class of an inner class?
|
||||
if (searchEnclosingClass(clazz)) {
|
||||
// Then mimic @Inherited semantics within the enclosing class hierarchy.
|
||||
return getMergedRepeatableAnnotations(clazz.getEnclosingClass(), annotationType);
|
||||
}
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the {@link AnnotationDescriptor} for the supplied {@code annotationType}
|
||||
* on the supplied {@link Class}, traversing its annotations, interfaces, and
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
|
@ -18,6 +18,7 @@ package org.springframework.test.context.jdbc;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -182,86 +183,62 @@ class MergedSqlConfigTests {
|
|||
.withMessage("You may declare the 'commentPrefix' or 'commentPrefixes' attribute in @SqlConfig but not both");
|
||||
}
|
||||
|
||||
@Test
|
||||
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);
|
||||
@Nested
|
||||
class TopLevelMergedSqlConfigTests {
|
||||
|
||||
@Test
|
||||
void globalConfigWithDefaults() throws Exception {
|
||||
assertGlobalConfigWithDefaults(GlobalConfigWithDefaultsClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfig() throws Exception {
|
||||
assertGlobalConfig(GlobalConfigClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfigWithLocalOverrides() throws Exception {
|
||||
assertGlobalConfigWithLocalOverrides(GlobalConfigClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfigWithCommentPrefixAndLocalOverrides() throws Exception {
|
||||
assertGlobalConfigWithCommentPrefixAndLocalOverrides(GlobalConfigWithPrefixClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfigWithCommentPrefixesAndLocalOverrides() throws Exception {
|
||||
assertGlobalConfigWithCommentPrefixesAndLocalOverrides(GlobalConfigWithPrefixesClass.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfig() throws Exception {
|
||||
Method method = GlobalConfigClass.class.getMethod("globalConfigMethod");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, GlobalConfigClass.class);
|
||||
@Nested
|
||||
class NestedMergedSqlConfigTests {
|
||||
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(cfg).isNotNull();
|
||||
softly.assertThat(cfg.getDataSource()).as("dataSource").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionManager()).as("transactionManager").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionMode()).as("transactionMode").isEqualTo(INFERRED);
|
||||
softly.assertThat(cfg.getEncoding()).as("encoding").isEqualTo("global");
|
||||
softly.assertThat(cfg.getSeparator()).as("separator").isEqualTo("\n");
|
||||
softly.assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("`", "--"));
|
||||
softly.assertThat(cfg.getBlockCommentStartDelimiter()).as("blockCommentStartDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_START_DELIMITER);
|
||||
softly.assertThat(cfg.getBlockCommentEndDelimiter()).as("blockCommentEndDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_END_DELIMITER);
|
||||
softly.assertThat(cfg.getErrorMode()).as("errorMode").isEqualTo(IGNORE_FAILED_DROPS);
|
||||
});
|
||||
}
|
||||
@Test
|
||||
void globalConfigWithDefaults() throws Exception {
|
||||
assertGlobalConfigWithDefaults(GlobalConfigWithDefaultsClass.Nested.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfigWithLocalOverrides() throws Exception {
|
||||
Method method = GlobalConfigClass.class.getMethod("globalConfigWithLocalOverridesMethod");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, GlobalConfigClass.class);
|
||||
@Test
|
||||
void globalConfig() throws Exception {
|
||||
assertGlobalConfig(GlobalConfigClass.Nested.class);
|
||||
}
|
||||
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(cfg).isNotNull();
|
||||
softly.assertThat(cfg.getDataSource()).as("dataSource").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionManager()).as("transactionManager").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionMode()).as("transactionMode").isEqualTo(INFERRED);
|
||||
softly.assertThat(cfg.getEncoding()).as("encoding").isEqualTo("local");
|
||||
softly.assertThat(cfg.getSeparator()).as("separator").isEqualTo("@@");
|
||||
softly.assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#"));
|
||||
softly.assertThat(cfg.getBlockCommentStartDelimiter()).as("blockCommentStartDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_START_DELIMITER);
|
||||
softly.assertThat(cfg.getBlockCommentEndDelimiter()).as("blockCommentEndDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_END_DELIMITER);
|
||||
softly.assertThat(cfg.getErrorMode()).as("errorMode").isEqualTo(CONTINUE_ON_ERROR);
|
||||
});
|
||||
}
|
||||
@Test
|
||||
void globalConfigWithLocalOverrides() throws Exception {
|
||||
assertGlobalConfigWithLocalOverrides(GlobalConfigClass.Nested.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfigWithCommentPrefixAndLocalOverrides() throws Exception {
|
||||
Class<?> testClass = GlobalConfigWithPrefixClass.class;
|
||||
@Test
|
||||
void globalConfigWithCommentPrefixAndLocalOverrides() throws Exception {
|
||||
assertGlobalConfigWithCommentPrefixAndLocalOverrides(GlobalConfigWithPrefixClass.Nested.class);
|
||||
}
|
||||
|
||||
Method method = testClass.getMethod("commentPrefixesOverrideCommentPrefix");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#", "@"));
|
||||
|
||||
method = testClass.getMethod("commentPrefixOverridesCommentPrefix");
|
||||
localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalConfigWithCommentPrefixesAndLocalOverrides() throws Exception {
|
||||
Class<?> testClass = GlobalConfigWithPrefixesClass.class;
|
||||
|
||||
Method method = testClass.getMethod("commentPrefixesOverrideCommentPrefixes");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#", "@"));
|
||||
|
||||
method = testClass.getMethod("commentPrefixOverridesCommentPrefixes");
|
||||
localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#"));
|
||||
@Test
|
||||
void globalConfigWithCommentPrefixesAndLocalOverrides() throws Exception {
|
||||
assertGlobalConfigWithCommentPrefixesAndLocalOverrides(GlobalConfigWithPrefixesClass.Nested.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertDefaults(MergedSqlConfig cfg) {
|
||||
|
|
@ -279,6 +256,79 @@ class MergedSqlConfigTests {
|
|||
});
|
||||
}
|
||||
|
||||
private void assertGlobalConfigWithDefaults(Class<?> testClass) throws Exception {
|
||||
Method method = testClass.getMethod("globalConfigMethod");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
assertDefaults(cfg);
|
||||
}
|
||||
|
||||
private void assertGlobalConfig(Class<?> testClass) throws NoSuchMethodException {
|
||||
Method method = testClass.getMethod("globalConfigMethod");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(cfg).isNotNull();
|
||||
softly.assertThat(cfg.getDataSource()).as("dataSource").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionManager()).as("transactionManager").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionMode()).as("transactionMode").isEqualTo(INFERRED);
|
||||
softly.assertThat(cfg.getEncoding()).as("encoding").isEqualTo("global");
|
||||
softly.assertThat(cfg.getSeparator()).as("separator").isEqualTo("\n");
|
||||
softly.assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("`", "--"));
|
||||
softly.assertThat(cfg.getBlockCommentStartDelimiter()).as("blockCommentStartDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_START_DELIMITER);
|
||||
softly.assertThat(cfg.getBlockCommentEndDelimiter()).as("blockCommentEndDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_END_DELIMITER);
|
||||
softly.assertThat(cfg.getErrorMode()).as("errorMode").isEqualTo(IGNORE_FAILED_DROPS);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertGlobalConfigWithLocalOverrides(Class<?> testClass) throws Exception {
|
||||
Method method = testClass.getMethod("globalConfigWithLocalOverridesMethod");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(cfg).isNotNull();
|
||||
softly.assertThat(cfg.getDataSource()).as("dataSource").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionManager()).as("transactionManager").isEqualTo("");
|
||||
softly.assertThat(cfg.getTransactionMode()).as("transactionMode").isEqualTo(INFERRED);
|
||||
softly.assertThat(cfg.getEncoding()).as("encoding").isEqualTo("local");
|
||||
softly.assertThat(cfg.getSeparator()).as("separator").isEqualTo("@@");
|
||||
softly.assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#"));
|
||||
softly.assertThat(cfg.getBlockCommentStartDelimiter()).as("blockCommentStartDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_START_DELIMITER);
|
||||
softly.assertThat(cfg.getBlockCommentEndDelimiter()).as("blockCommentEndDelimiter").isEqualTo(DEFAULT_BLOCK_COMMENT_END_DELIMITER);
|
||||
softly.assertThat(cfg.getErrorMode()).as("errorMode").isEqualTo(CONTINUE_ON_ERROR);
|
||||
});
|
||||
}
|
||||
|
||||
private void assertGlobalConfigWithCommentPrefixAndLocalOverrides(Class<?> testClass) throws Exception {
|
||||
Method method = testClass.getMethod("commentPrefixesOverrideCommentPrefix");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#", "@"));
|
||||
|
||||
method = testClass.getMethod("commentPrefixOverridesCommentPrefix");
|
||||
localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#"));
|
||||
}
|
||||
|
||||
private void assertGlobalConfigWithCommentPrefixesAndLocalOverrides(Class<?> testClass) throws Exception {
|
||||
Method method = testClass.getMethod("commentPrefixesOverrideCommentPrefixes");
|
||||
SqlConfig localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
MergedSqlConfig cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#", "@"));
|
||||
|
||||
method = testClass.getMethod("commentPrefixOverridesCommentPrefixes");
|
||||
localSqlConfig = method.getAnnotation(Sql.class).config();
|
||||
cfg = new MergedSqlConfig(localSqlConfig, testClass);
|
||||
|
||||
assertThat(cfg.getCommentPrefixes()).as("commentPrefixes").isEqualTo(array("#"));
|
||||
}
|
||||
|
||||
private static String[] array(String... elements) {
|
||||
return elements;
|
||||
}
|
||||
|
|
@ -339,6 +389,13 @@ class MergedSqlConfigTests {
|
|||
@Sql
|
||||
public void globalConfigMethod() {
|
||||
}
|
||||
|
||||
class Nested {
|
||||
|
||||
@Sql
|
||||
public void globalConfigMethod() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SqlConfig(encoding = "global", separator = "\n", commentPrefixes = { "`", "--" }, errorMode = IGNORE_FAILED_DROPS)
|
||||
|
|
@ -351,6 +408,17 @@ class MergedSqlConfigTests {
|
|||
@Sql(config = @SqlConfig(encoding = "local", separator = "@@", commentPrefix = "#", errorMode = CONTINUE_ON_ERROR))
|
||||
public void globalConfigWithLocalOverridesMethod() {
|
||||
}
|
||||
|
||||
class Nested {
|
||||
|
||||
@Sql
|
||||
public void globalConfigMethod() {
|
||||
}
|
||||
|
||||
@Sql(config = @SqlConfig(encoding = "local", separator = "@@", commentPrefix = "#", errorMode = CONTINUE_ON_ERROR))
|
||||
public void globalConfigWithLocalOverridesMethod() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SqlConfig(commentPrefix = "`")
|
||||
|
|
@ -363,6 +431,17 @@ class MergedSqlConfigTests {
|
|||
@Sql(config = @SqlConfig(commentPrefix = "#"))
|
||||
public void commentPrefixOverridesCommentPrefix() {
|
||||
}
|
||||
|
||||
class Nested {
|
||||
|
||||
@Sql(config = @SqlConfig(commentPrefixes = { "#", "@" }))
|
||||
public void commentPrefixesOverrideCommentPrefix() {
|
||||
}
|
||||
|
||||
@Sql(config = @SqlConfig(commentPrefix = "#"))
|
||||
public void commentPrefixOverridesCommentPrefix() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SqlConfig(commentPrefixes = { "`", "--" })
|
||||
|
|
@ -375,6 +454,17 @@ class MergedSqlConfigTests {
|
|||
@Sql(config = @SqlConfig(commentPrefix = "#"))
|
||||
public void commentPrefixOverridesCommentPrefixes() {
|
||||
}
|
||||
|
||||
class Nested {
|
||||
|
||||
@Sql(config = @SqlConfig(commentPrefixes = { "#", "@" }))
|
||||
public void commentPrefixesOverrideCommentPrefixes() {
|
||||
}
|
||||
|
||||
@Sql(config = @SqlConfig(commentPrefix = "#"))
|
||||
public void commentPrefixOverridesCommentPrefixes() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright 2002-2020 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
|
||||
*
|
||||
* https://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.Inherited;
|
||||
import java.lang.annotation.Repeatable;
|
||||
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Subclass of {@link RepeatableSqlAnnotationSqlScriptsParentTests} which verifies
|
||||
* that {@link Repeatable} {@link Sql @Sql} annotations are not
|
||||
* {@linkplain Inherited @Inherited} from a superclass if the subclass has local
|
||||
* {@code @Sql} declarations.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@Sql("schema.sql")
|
||||
@Sql("data-add-catbert.sql")
|
||||
class RepeatableSqlAnnotationSqlScriptsChildTests extends RepeatableSqlAnnotationSqlScriptsParentTests {
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
@Override
|
||||
void classLevelScripts() {
|
||||
// Should not find Dilbert, since local @Sql declarations shadow @Sql
|
||||
// declarations on a superclass. This is due to the fact that we use
|
||||
// "get" semantics instead of "find" semantics when searching for @Sql.
|
||||
assertUsers("Catbert");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
|
@ -38,12 +38,12 @@ import org.springframework.test.context.ContextConfiguration;
|
|||
@Sql("schema.sql")
|
||||
@Sql("data.sql")
|
||||
@DirtiesContext
|
||||
class RepeatableSqlAnnotationSqlScriptsTests extends AbstractTransactionalTests {
|
||||
class RepeatableSqlAnnotationSqlScriptsParentTests extends AbstractTransactionalTests {
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
void classLevelScripts() {
|
||||
assertNumUsers(1);
|
||||
assertUsers("Dilbert");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -51,9 +51,9 @@ class RepeatableSqlAnnotationSqlScriptsTests extends AbstractTransactionalTests
|
|||
@Sql("schema.sql")
|
||||
@Sql("data.sql")
|
||||
@Sql("data-add-dogbert.sql")
|
||||
@Order(1)
|
||||
@Order(2)
|
||||
void methodLevelScripts() {
|
||||
assertNumUsers(2);
|
||||
assertUsers("Dilbert", "Dogbert");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -30,6 +30,6 @@ import org.springframework.test.context.jdbc.SqlMergeMode;
|
|||
*/
|
||||
@ContextConfiguration(classes = EmptyDatabaseConfig.class)
|
||||
@DirtiesContext
|
||||
abstract class AbstractSqlMergeModeTests extends AbstractTransactionalTests {
|
||||
public abstract class AbstractSqlMergeModeTests extends AbstractTransactionalTests {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,13 @@ import org.junit.jupiter.api.TestInstance.Lifecycle;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration;
|
||||
import org.springframework.test.context.jdbc.PopulatedSchemaDatabaseConfig;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.SqlMergeMode;
|
||||
import org.springframework.test.context.jdbc.SqlMergeMode.MergeMode;
|
||||
import org.springframework.test.context.jdbc.merging.AbstractSqlMergeModeTests;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
|
|
@ -33,6 +38,8 @@ import org.springframework.test.jdbc.JdbcTestUtils;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.context.jdbc.SqlMergeMode.MergeMode.MERGE;
|
||||
import static org.springframework.test.context.jdbc.SqlMergeMode.MergeMode.OVERRIDE;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for {@link Nested @Nested} test classes in
|
||||
|
|
@ -69,9 +76,6 @@ class SqlScriptNestedTests {
|
|||
@Nested
|
||||
class NestedTests {
|
||||
|
||||
@Autowired
|
||||
JdbcTemplate jdbcTemplate;
|
||||
|
||||
@BeforeTransaction
|
||||
@AfterTransaction
|
||||
void checkInitialDatabaseState() {
|
||||
|
|
@ -83,9 +87,72 @@ class SqlScriptNestedTests {
|
|||
void nestedSqlScripts() {
|
||||
assertThat(countRowsInTable("user")).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
|
||||
private int countRowsInTable(String tableName) {
|
||||
return JdbcTestUtils.countRowsInTable(this.jdbcTemplate, tableName);
|
||||
@Nested
|
||||
@NestedTestConfiguration(EnclosingConfiguration.OVERRIDE)
|
||||
@Sql({
|
||||
"/org/springframework/test/context/jdbc/recreate-schema.sql",
|
||||
"/org/springframework/test/context/jdbc/data-add-catbert.sql"
|
||||
})
|
||||
class NestedSqlMergeModeTests extends AbstractSqlMergeModeTests {
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(EnclosingConfiguration.INHERIT)
|
||||
@SqlMergeMode(MergeMode.MERGE)
|
||||
class NestedClassLevelMergeSqlMergeModeTests {
|
||||
|
||||
@Test
|
||||
void classLevelScripts() {
|
||||
assertUsers("Catbert");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Sql("/org/springframework/test/context/jdbc/data-add-dogbert.sql")
|
||||
void merged() {
|
||||
assertUsers("Catbert", "Dogbert");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Sql({
|
||||
"/org/springframework/test/context/jdbc/recreate-schema.sql",
|
||||
"/org/springframework/test/context/jdbc/data.sql",
|
||||
"/org/springframework/test/context/jdbc/data-add-dogbert.sql",
|
||||
"/org/springframework/test/context/jdbc/data-add-catbert.sql"
|
||||
})
|
||||
@SqlMergeMode(MergeMode.OVERRIDE)
|
||||
void overridden() {
|
||||
assertUsers("Dilbert", "Dogbert", "Catbert");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(EnclosingConfiguration.INHERIT)
|
||||
@SqlMergeMode(OVERRIDE)
|
||||
class ClassLevelOverrideSqlMergeModeTests {
|
||||
|
||||
@Test
|
||||
void classLevelScripts() {
|
||||
assertUsers("Catbert");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Sql("/org/springframework/test/context/jdbc/data-add-dogbert.sql")
|
||||
@SqlMergeMode(MERGE)
|
||||
void merged() {
|
||||
assertUsers("Catbert", "Dogbert");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Sql({
|
||||
"/org/springframework/test/context/jdbc/recreate-schema.sql",
|
||||
"/org/springframework/test/context/jdbc/data.sql",
|
||||
"/org/springframework/test/context/jdbc/data-add-dogbert.sql",
|
||||
"/org/springframework/test/context/jdbc/data-add-catbert.sql"
|
||||
})
|
||||
void overridden() {
|
||||
assertUsers("Dilbert", "Dogbert", "Catbert");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1882,6 +1882,9 @@ following annotations.
|
|||
* <<testcontext-tx,`@Transactional`>>
|
||||
* <<spring-testing-annotation-commit>>
|
||||
* <<spring-testing-annotation-rollback>>
|
||||
* <<spring-testing-annotation-sql>>
|
||||
* <<spring-testing-annotation-sqlconfig>>
|
||||
* <<spring-testing-annotation-sqlmergemode>>
|
||||
* <<integration-testing-annotations-testconstructor>>
|
||||
|
||||
NOTE: The use of `@NestedTestConfiguration` typically only makes sense in conjunction
|
||||
|
|
|
|||
Loading…
Reference in New Issue