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:
Sam Brannen
2020-10-22 17:01:32 +02:00
parent 95110d8257
commit b8b854db8c
10 changed files with 376 additions and 97 deletions

View File

@@ -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() {
}
}
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}

View File

@@ -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 {
}

View File

@@ -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");
}
}
}