diff --git a/spring-context/src/test/java/org/springframework/tests/sample/beans/Employee.java b/spring-context/src/test/java/org/springframework/tests/sample/beans/Employee.java index 40301c7a24b..fc2c639fa5c 100644 --- a/spring-context/src/test/java/org/springframework/tests/sample/beans/Employee.java +++ b/spring-context/src/test/java/org/springframework/tests/sample/beans/Employee.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * 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. @@ -20,6 +20,13 @@ public class Employee extends TestBean { private String co; + public Employee() { + } + + public Employee(String name) { + super(name); + } + public String getCompany() { return co; } diff --git a/spring-test/src/main/java/org/springframework/test/annotation/Commit.java b/spring-test/src/main/java/org/springframework/test/annotation/Commit.java index e23c254fba6..98b3d96b0ab 100644 --- a/spring-test/src/main/java/org/springframework/test/annotation/Commit.java +++ b/spring-test/src/main/java/org/springframework/test/annotation/Commit.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -18,6 +18,7 @@ package org.springframework.test.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -51,6 +52,7 @@ import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented +@Inherited @Rollback(false) public @interface Commit { } diff --git a/spring-test/src/main/java/org/springframework/test/annotation/ProfileValueSourceConfiguration.java b/spring-test/src/main/java/org/springframework/test/annotation/ProfileValueSourceConfiguration.java index cd285587981..e5f61e45a8b 100644 --- a/spring-test/src/main/java/org/springframework/test/annotation/ProfileValueSourceConfiguration.java +++ b/spring-test/src/main/java/org/springframework/test/annotation/ProfileValueSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * 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. @@ -24,7 +24,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - *

{@code ProfileValueSourceConfiguration} is a class-level annotation which + * {@code ProfileValueSourceConfiguration} is a class-level annotation which * is used to specify what type of {@link ProfileValueSource} to use when * retrieving profile values configured via the {@link IfProfileValue * @IfProfileValue} annotation. @@ -38,17 +38,15 @@ import java.lang.annotation.Target; * @see IfProfileValue * @see ProfileValueUtils */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface ProfileValueSourceConfiguration { /** - *

* The type of {@link ProfileValueSource} to use when retrieving * profile values. - *

* * @see SystemProfileValueSource */ diff --git a/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java b/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java index 37bf2102791..c1f06e643f5 100644 --- a/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java +++ b/spring-test/src/main/java/org/springframework/test/annotation/Rollback.java @@ -18,6 +18,7 @@ package org.springframework.test.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @@ -56,6 +57,7 @@ import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented +@Inherited public @interface Rollback { /** diff --git a/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java b/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java index fc259102edd..54b08892975 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java +++ b/spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java @@ -43,10 +43,10 @@ import org.springframework.core.annotation.AliasFor; * @see org.springframework.context.ApplicationContext * @see org.springframework.context.annotation.Profile */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface ActiveProfiles { /** diff --git a/spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java b/spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java index 7f26cc2aac6..2567a977927 100644 --- a/spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java @@ -17,16 +17,15 @@ package org.springframework.test.context; import java.lang.reflect.Constructor; -import java.util.List; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanUtils; import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.util.ClassUtils; -import org.springframework.util.MultiValueMap; /** * {@code BootstrapUtils} is a collection of utility methods to assist with @@ -151,17 +150,16 @@ abstract class BootstrapUtils { * @since 4.3 */ private static Class resolveExplicitTestContextBootstrapper(Class testClass) { - MultiValueMap attributesMultiMap = - AnnotatedElementUtils.getAllAnnotationAttributes(testClass, BootstrapWith.class.getName()); - List values = (attributesMultiMap != null ? attributesMultiMap.get(AnnotationUtils.VALUE) : null); - if (values == null) { + Set annotations = AnnotatedElementUtils.findAllMergedAnnotations(testClass, BootstrapWith.class); + if (annotations.size() < 1) { return null; } - if (values.size() != 1) { - throw new IllegalStateException(String.format("Configuration error: found multiple declarations of " + - "@BootstrapWith on test class [%s] with values %s", testClass.getName(), values)); + if (annotations.size() > 1) { + throw new IllegalStateException(String.format( + "Configuration error: found multiple declarations of @BootstrapWith for test class [%s]: %s", + testClass.getName(), annotations)); } - return (Class) values.get(0); + return annotations.iterator().next().value(); } /** @@ -169,7 +167,9 @@ abstract class BootstrapUtils { */ private static Class resolveDefaultTestContextBootstrapper(Class testClass) throws Exception { ClassLoader classLoader = BootstrapUtils.class.getClassLoader(); - if (AnnotatedElementUtils.isAnnotated(testClass, WEB_APP_CONFIGURATION_ANNOTATION_CLASS_NAME)) { + AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(testClass, + WEB_APP_CONFIGURATION_ANNOTATION_CLASS_NAME, false, false); + if (attributes != null) { return ClassUtils.forName(DEFAULT_WEB_TEST_CONTEXT_BOOTSTRAPPER_CLASS_NAME, classLoader); } return ClassUtils.forName(DEFAULT_TEST_CONTEXT_BOOTSTRAPPER_CLASS_NAME, classLoader); diff --git a/spring-test/src/main/java/org/springframework/test/context/BootstrapWith.java b/spring-test/src/main/java/org/springframework/test/context/BootstrapWith.java index 302ce42e2a3..7cf742f6330 100644 --- a/spring-test/src/main/java/org/springframework/test/context/BootstrapWith.java +++ b/spring-test/src/main/java/org/springframework/test/context/BootstrapWith.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * 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. @@ -35,10 +35,10 @@ import java.lang.annotation.Target; * @see BootstrapContext * @see TestContextBootstrapper */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface BootstrapWith { /** diff --git a/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java b/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java index 9087bdbeafb..669adbd65c7 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java +++ b/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * 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. @@ -83,10 +83,10 @@ import org.springframework.core.annotation.AliasFor; * @see MergedContextConfiguration * @see org.springframework.context.ApplicationContext */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface ContextConfiguration { /** diff --git a/spring-test/src/main/java/org/springframework/test/context/ContextHierarchy.java b/spring-test/src/main/java/org/springframework/test/context/ContextHierarchy.java index 61b2fa8cf61..3a3d2859799 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ContextHierarchy.java +++ b/spring-test/src/main/java/org/springframework/test/context/ContextHierarchy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -139,10 +139,10 @@ import java.lang.annotation.Target; * @see ContextConfiguration * @see org.springframework.context.ApplicationContext */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface ContextHierarchy { /** diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java index d99c48d7aa9..d1db5c75c91 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java @@ -42,10 +42,10 @@ import org.springframework.core.annotation.AliasFor; * @see TestContextManager * @see ContextConfiguration */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface TestExecutionListeners { /** diff --git a/spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java b/spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java index ec2528af29a..6937870bbf5 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java @@ -82,10 +82,10 @@ import org.springframework.core.annotation.AliasFor; * @see org.springframework.core.env.PropertySource * @see org.springframework.context.annotation.PropertySource */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) @Documented @Inherited -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) public @interface TestPropertySource { /** diff --git a/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java b/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java index 913986a4402..9c203d743e2 100644 --- a/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java +++ b/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java @@ -57,8 +57,8 @@ public abstract class MetaAnnotationUtils { /** * Find the {@link AnnotationDescriptor} for the supplied {@code annotationType} - * on the supplied {@link Class}, traversing its annotations and superclasses - * if no annotation can be found on the given class itself. + * on the supplied {@link Class}, traversing its annotations, interfaces, and + * superclasses if no annotation can be found on the given class itself. *

This method explicitly handles class-level annotations which are not * declared as {@linkplain java.lang.annotation.Inherited inherited} as * well as meta-annotations. @@ -67,14 +67,12 @@ public abstract class MetaAnnotationUtils { *

  • Search for the annotation on the given class and return a corresponding * {@code AnnotationDescriptor} if found. *
  • Recursively search through all annotations that the given class declares. + *
  • Recursively search through all interfaces implemented by the given class. *
  • Recursively search through the superclass hierarchy of the given class. * *

    In this context, the term recursively means that the search - * process continues by returning to step #1 with the current annotation or - * superclass as the class to look for annotations on. - *

    If the supplied {@code clazz} is an interface, only the interface - * itself will be checked; the inheritance hierarchy for interfaces will not - * be traversed. + * process continues by returning to step #1 with the current annotation, + * interface, or superclass as the class to look for annotations on. * @param clazz the class to look for annotations on * @param annotationType the type of annotation to look for * @return the corresponding annotation descriptor if the annotation was found; @@ -123,6 +121,15 @@ public abstract class MetaAnnotationUtils { } } + // Declared on interface? + for (Class ifc : clazz.getInterfaces()) { + AnnotationDescriptor descriptor = findAnnotationDescriptor(ifc, visited, annotationType); + if (descriptor != null) { + return new AnnotationDescriptor(clazz, descriptor.getDeclaringClass(), + descriptor.getComposedAnnotation(), descriptor.getAnnotation()); + } + } + // Declared on a superclass? return findAnnotationDescriptor(clazz.getSuperclass(), visited, annotationType); } @@ -132,8 +139,9 @@ public abstract class MetaAnnotationUtils { * in the inheritance hierarchy of the specified {@code clazz} (including * the specified {@code clazz} itself) which declares at least one of the * specified {@code annotationTypes}. - *

    This method traverses the annotations and superclasses of the specified - * {@code clazz} if no annotation can be found on the given class itself. + *

    This method traverses the annotations, interfaces, and superclasses + * of the specified {@code clazz} if no annotation can be found on the given + * class itself. *

    This method explicitly handles class-level annotations which are not * declared as {@linkplain java.lang.annotation.Inherited inherited} as * well as meta-annotations. @@ -143,14 +151,12 @@ public abstract class MetaAnnotationUtils { * the given class and return a corresponding {@code UntypedAnnotationDescriptor} * if found. *

  • Recursively search through all annotations that the given class declares. + *
  • Recursively search through all interfaces implemented by the given class. *
  • Recursively search through the superclass hierarchy of the given class. * *

    In this context, the term recursively means that the search - * process continues by returning to step #1 with the current annotation or - * superclass as the class to look for annotations on. - *

    If the supplied {@code clazz} is an interface, only the interface - * itself will be checked; the inheritance hierarchy for interfaces will not - * be traversed. + * process continues by returning to step #1 with the current annotation, + * interface, or superclass as the class to look for annotations on. * @param clazz the class to look for annotations on * @param annotationTypes the types of annotations to look for * @return the corresponding annotation descriptor if one of the annotations @@ -203,6 +209,15 @@ public abstract class MetaAnnotationUtils { } } + // Declared on interface? + for (Class ifc : clazz.getInterfaces()) { + UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(ifc, visited, annotationTypes); + if (descriptor != null) { + return new UntypedAnnotationDescriptor(clazz, descriptor.getDeclaringClass(), + descriptor.getComposedAnnotation(), descriptor.getAnnotation()); + } + } + // Declared on a superclass? return findAnnotationDescriptorForTypes(clazz.getSuperclass(), visited, annotationTypes); } diff --git a/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java b/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java index 4296fd077da..da461beec00 100644 --- a/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * 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. @@ -91,7 +91,10 @@ public class ProfileValueUtilsTests { assertClassIsEnabled(EnabledAnnotatedMultiValue.class); assertClassIsEnabled(MetaEnabledClass.class); assertClassIsEnabled(MetaEnabledWithCustomProfileValueSourceClass.class); + assertClassIsEnabled(EnabledWithCustomProfileValueSourceOnTestInterface.class); + assertClassIsDisabled(DisabledAnnotatedSingleValue.class); + assertClassIsDisabled(DisabledAnnotatedSingleValueOnTestInterface.class); assertClassIsDisabled(DisabledAnnotatedMultiValue.class); assertClassIsDisabled(MetaDisabledClass.class); assertClassIsDisabled(MetaDisabledWithCustomProfileValueSourceClass.class); @@ -105,6 +108,7 @@ public class ProfileValueUtilsTests { assertMethodIsEnabled(ENABLED_ANNOTATED_METHOD, EnabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, EnabledAnnotatedSingleValue.class); + assertMethodIsEnabled(NON_ANNOTATED_METHOD, MetaEnabledAnnotatedSingleValue.class); assertMethodIsEnabled(ENABLED_ANNOTATED_METHOD, MetaEnabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, MetaEnabledAnnotatedSingleValue.class); @@ -117,6 +121,8 @@ public class ProfileValueUtilsTests { assertMethodIsDisabled(ENABLED_ANNOTATED_METHOD, DisabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, DisabledAnnotatedSingleValue.class); + assertMethodIsDisabled(NON_ANNOTATED_METHOD, DisabledAnnotatedSingleValueOnTestInterface.class); + assertMethodIsDisabled(NON_ANNOTATED_METHOD, MetaDisabledAnnotatedSingleValue.class); assertMethodIsDisabled(ENABLED_ANNOTATED_METHOD, MetaDisabledAnnotatedSingleValue.class); assertMethodIsDisabled(DISABLED_ANNOTATED_METHOD, MetaDisabledAnnotatedSingleValue.class); @@ -176,6 +182,17 @@ public class ProfileValueUtilsTests { } } + @IfProfileValue(name = NAME, value = VALUE + "X") + private interface IfProfileValueTestInterface { + } + + @SuppressWarnings("unused") + private static class DisabledAnnotatedSingleValueOnTestInterface implements IfProfileValueTestInterface { + + public void nonAnnotatedMethod() { + } + } + @SuppressWarnings("unused") @IfProfileValue(name = NAME, values = { "foo", VALUE, "bar" }) private static class EnabledAnnotatedMultiValue { @@ -302,4 +319,13 @@ public class ProfileValueUtilsTests { private static class MetaDisabledWithCustomProfileValueSourceClass { } + @ProfileValueSourceConfiguration(HardCodedProfileValueSource.class) + private interface CustomProfileValueSourceTestInterface { + } + + @IfProfileValue(name = NAME, value = "42") + private static class EnabledWithCustomProfileValueSourceOnTestInterface + implements CustomProfileValueSourceTestInterface { + } + } diff --git a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java index 648655fb9cf..4df53d82ffa 100644 --- a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java @@ -115,6 +115,12 @@ public class TestExecutionListenersTests { assertNumRegisteredListeners(ExplicitListenersTestCase.class, 3); } + @Test + public void customListenersDeclaredOnInterface() { + assertRegisteredListeners(ExplicitListenersOnTestInterfaceTestCase.class, + asList(FooTestExecutionListener.class, BarTestExecutionListener.class)); + } + @Test public void nonInheritedListeners() { assertNumRegisteredListeners(NonInheritedListenersTestCase.class, 1); @@ -229,6 +235,13 @@ public class TestExecutionListenersTests { static class NonInheritedListenersTestCase extends InheritedListenersTestCase { } + @TestExecutionListeners({ FooTestExecutionListener.class, BarTestExecutionListener.class }) + interface ExplicitListenersTestInterface { + } + + static class ExplicitListenersOnTestInterfaceTestCase implements ExplicitListenersTestInterface { + } + @TestExecutionListeners(listeners = FooTestExecutionListener.class, value = BarTestExecutionListener.class) static class DuplicateListenersConfigTestCase { } diff --git a/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java b/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java index 896c4654a81..9da13e7bcf6 100644 --- a/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -30,10 +30,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; 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.test.context.support.DirtiesContextTestExecutionListener; +import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.*; import static org.springframework.test.context.cache.ContextCacheTestUtils.*; @@ -41,9 +38,8 @@ import static org.springframework.test.context.junit4.JUnitTestingUtils.*; /** * JUnit 4 based integration test which verifies correct {@linkplain ContextCache - * application context caching} in conjunction with the - * {@link SpringJUnit4ClassRunner} and {@link DirtiesContext @DirtiesContext} - * at the class level. + * application context caching} in conjunction with the {@link SpringRunner} and + * {@link DirtiesContext @DirtiesContext} at the class level. * * @author Sam Brannen * @since 3.0 @@ -148,10 +144,9 @@ public class ClassLevelDirtiesContextTests { // ------------------------------------------------------------------- - @RunWith(SpringJUnit4ClassRunner.class) - @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) + @RunWith(SpringRunner.class) @ContextConfiguration - public static abstract class BaseTestCase { + static abstract class BaseTestCase { @Configuration static class Config { diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java new file mode 100644 index 00000000000..80d33c8d1a3 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java @@ -0,0 +1,65 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.tests.sample.beans.Employee; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class ActiveProfilesInterfaceTests implements ActiveProfilesTestInterface { + + @Autowired + Employee employee; + + + @Test + public void profileFromTestInterface() { + assertNotNull(employee); + assertEquals("dev", employee.getName()); + } + + + @Configuration + static class Config { + + @Bean + @Profile("dev") + Employee employee1() { + return new Employee("dev"); + } + + @Bean + @Profile("prod") + Employee employee2() { + return new Employee("prod"); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java new file mode 100644 index 00000000000..63ef2004f9b --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java @@ -0,0 +1,27 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.test.context.ActiveProfiles; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ActiveProfiles("dev") +interface ActiveProfilesTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java new file mode 100644 index 00000000000..47e52b9ffda --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java @@ -0,0 +1,43 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class BootstrapWithInterfaceTests implements BootstrapWithTestInterface { + + @Autowired + String foo; + + + @Test + public void injectedBean() { + assertEquals("foo", foo); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java new file mode 100644 index 00000000000..993f3afaed9 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java @@ -0,0 +1,47 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import java.util.List; + +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.ContextCustomizer; +import org.springframework.test.context.ContextCustomizerFactory; +import org.springframework.test.context.configuration.interfaces.BootstrapWithTestInterface.CustomTestContextBootstrapper; +import org.springframework.test.context.support.DefaultTestContextBootstrapper; + +import static java.util.Collections.*; + +/** + * @author Sam Brannen + * @author Phillip Webb + * @since 4.3 + */ +@BootstrapWith(CustomTestContextBootstrapper.class) +interface BootstrapWithTestInterface { + + static class CustomTestContextBootstrapper extends DefaultTestContextBootstrapper { + + @Override + protected List getContextCustomizerFactories() { + return singletonList( + (ContextCustomizerFactory) (testClass, configAttributes) -> (ContextCustomizer) (context, + mergedConfig) -> context.getBeanFactory().registerSingleton("foo", "foo")); + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java new file mode 100644 index 00000000000..4a035e77a04 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java @@ -0,0 +1,45 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.tests.sample.beans.Employee; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class ContextConfigurationInterfaceTests implements ContextConfigurationTestInterface { + + @Autowired + Employee employee; + + + @Test + public void profileFromTestInterface() { + assertNotNull(employee); + assertEquals("Dilbert", employee.getName()); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java new file mode 100644 index 00000000000..7eb452fcec5 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java @@ -0,0 +1,39 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.configuration.interfaces.ContextConfigurationTestInterface.Config; +import org.springframework.tests.sample.beans.Employee; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ContextConfiguration(classes = Config.class) +interface ContextConfigurationTestInterface { + + static class Config { + + @Bean + Employee employee() { + return new Employee("Dilbert"); + } + } + +} \ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java new file mode 100644 index 00000000000..832c244b796 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class ContextHierarchyInterfaceTests implements ContextHierarchyTestInterface { + + @Autowired + String foo; + + @Autowired + String bar; + + @Autowired + String baz; + + @Autowired + ApplicationContext context; + + + @Test + public void loadContextHierarchy() { + assertNotNull("child ApplicationContext", context); + assertNotNull("parent ApplicationContext", context.getParent()); + assertNull("grandparent ApplicationContext", context.getParent().getParent()); + assertEquals("foo", foo); + assertEquals("bar", bar); + assertEquals("baz-child", baz); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java new file mode 100644 index 00000000000..538e2a932da --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java @@ -0,0 +1,31 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.ContextHierarchy; +import org.springframework.test.context.hierarchies.standard.SingleTestClassWithTwoLevelContextHierarchyTests; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ContextHierarchy({ + @ContextConfiguration(classes = SingleTestClassWithTwoLevelContextHierarchyTests.ParentConfig.class), + @ContextConfiguration(classes = SingleTestClassWithTwoLevelContextHierarchyTests.ChildConfig.class) }) +interface ContextHierarchyTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java new file mode 100644 index 00000000000..6b0be0a151a --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java @@ -0,0 +1,95 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.*; +import static org.springframework.test.context.cache.ContextCacheTestUtils.*; +import static org.springframework.test.context.junit4.JUnitTestingUtils.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(JUnit4.class) +public class DirtiesContextInterfaceTests { + + private static final AtomicInteger cacheHits = new AtomicInteger(0); + private static final AtomicInteger cacheMisses = new AtomicInteger(0); + + + @BeforeClass + public static void verifyInitialCacheState() { + resetContextCache(); + // Reset static counters in case tests are run multiple times in a test suite -- + // for example, via JUnit's @Suite. + cacheHits.set(0); + cacheMisses.set(0); + assertContextCacheStatistics("BeforeClass", 0, cacheHits.get(), cacheMisses.get()); + } + + @AfterClass + public static void verifyFinalCacheState() { + assertContextCacheStatistics("AfterClass", 0, cacheHits.get(), cacheMisses.get()); + } + + @Test + public void verifyDirtiesContextBehavior() throws Exception { + runTestClassAndAssertStats(ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase.class, 1); + assertContextCacheStatistics("after class-level @DirtiesContext with clean test method and default class mode", + 0, cacheHits.get(), cacheMisses.incrementAndGet()); + } + + private void runTestClassAndAssertStats(Class testClass, int expectedTestCount) throws Exception { + runTestsAndAssertCounters(testClass, expectedTestCount, 0, expectedTestCount, 0, 0); + } + + + @RunWith(SpringRunner.class) + public static class ClassLevelDirtiesContextWithCleanMethodsAndDefaultModeTestCase + implements DirtiesContextTestInterface { + + @Autowired + ApplicationContext applicationContext; + + + @Test + public void verifyContextWasAutowired() { + assertNotNull("The application context should have been autowired.", this.applicationContext); + } + + + @Configuration + static class Config { + /* no beans */ + } + + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java new file mode 100644 index 00000000000..cd486e14e7d --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java @@ -0,0 +1,27 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.test.annotation.DirtiesContext; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@DirtiesContext +interface DirtiesContextTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java new file mode 100644 index 00000000000..26f044f81be --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java @@ -0,0 +1,46 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; + +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +public class SqlConfigInterfaceTests extends AbstractTransactionalJUnit4SpringContextTests + implements SqlConfigTestInterface { + + @Test + @Sql(scripts = "/org/springframework/test/context/jdbc/schema.sql", // + config = @SqlConfig(separator = ";")) + @Sql("/org/springframework/test/context/jdbc/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")); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java new file mode 100644 index 00000000000..a707a4c2c0a --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java @@ -0,0 +1,32 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.jdbc.EmptyDatabaseConfig; +import org.springframework.test.context.jdbc.SqlConfig; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@ContextConfiguration(classes = EmptyDatabaseConfig.class) +@DirtiesContext +@SqlConfig(commentPrefix = "`", blockCommentStartDelimiter = "#$", blockCommentEndDelimiter = "$#", separator = "@@") +interface SqlConfigTestInterface { +} \ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java new file mode 100644 index 00000000000..66dd6057c2a --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java @@ -0,0 +1,57 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class TestPropertySourceInterfaceTests implements TestPropertySourceTestInterface { + + @Autowired + Environment env; + + + @Test + public void propertiesAreAvailableInEnvironment() { + assertThat(property("foo"), is("bar")); + assertThat(property("enigma"), is("42")); + } + + private String property(String key) { + return env.getProperty(key); + } + + + @Configuration + static class Config { + /* no user beans required for these tests */ + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java new file mode 100644 index 00000000000..af27989e088 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java @@ -0,0 +1,27 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.test.context.TestPropertySource; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@TestPropertySource(properties = { "foo = bar", "enigma: 42" }) +interface TestPropertySourceTestInterface { +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java new file mode 100644 index 00000000000..fdb6706be7e --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java @@ -0,0 +1,44 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.context.WebApplicationContext; + +import static org.junit.Assert.*; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@RunWith(SpringRunner.class) +public class WebAppConfigurationInterfaceTests implements WebAppConfigurationTestInterface { + + @Autowired + WebApplicationContext wac; + + + @Test + public void wacLoaded() { + assertNotNull(wac); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java new file mode 100644 index 00000000000..dcfabd14cb8 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java @@ -0,0 +1,37 @@ +/* + * 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 org.springframework.test.context.configuration.interfaces; + +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.configuration.interfaces.WebAppConfigurationTestInterface.Config; +import org.springframework.test.context.web.WebAppConfiguration; + +/** + * @author Sam Brannen + * @since 4.3 + */ +@WebAppConfiguration +@ContextConfiguration(classes = Config.class) +interface WebAppConfigurationTestInterface { + + @Configuration + static class Config { + /* no user beans required for these tests */ + } + +} \ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java b/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java index 2868b6944ee..f8ba83fd2bb 100644 --- a/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * 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. @@ -40,7 +40,7 @@ import static org.junit.Assert.*; public class SingleTestClassWithTwoLevelContextHierarchyTests { @Configuration - static class ParentConfig { + public static class ParentConfig { @Bean public String foo() { @@ -54,7 +54,7 @@ public class SingleTestClassWithTwoLevelContextHierarchyTests { } @Configuration - static class ChildConfig { + public static class ChildConfig { @Bean public String bar() { diff --git a/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java index 0e4f7276f8a..82cb00816e1 100644 --- a/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java @@ -54,6 +54,7 @@ public class TransactionalTestExecutionListenerTests { private final TransactionalTestExecutionListener listener = new TransactionalTestExecutionListener() { + @Override protected PlatformTransactionManager getTransactionManager(TestContext testContext, String qualifier) { return tm; } @@ -353,6 +354,16 @@ public class TransactionalTestExecutionListenerTests { assertIsRollback(ClassLevelRollbackViaMetaAnnotationTestCase.class, false); } + @Test + public void isRollbackWithClassLevelRollbackWithExplicitValueOnTestInterface() throws Exception { + assertIsRollback(ClassLevelRollbackWithExplicitValueOnTestInterfaceTestCase.class, false); + } + + @Test + public void isRollbackWithClassLevelRollbackViaMetaAnnotationOnTestInterface() throws Exception { + assertIsRollback(ClassLevelRollbackViaMetaAnnotationOnTestInterfaceTestCase.class, false); + } + @Test public void isRollbackWithRollbackAndTransactionConfigurationDeclaredAtClassLevel() throws Exception { Class clazz = ClassLevelRollbackAndTransactionConfigurationTestCase.class; @@ -712,4 +723,25 @@ public class TransactionalTestExecutionListenerTests { } } + @Rollback(false) + interface RollbackFalseTestInterface { + } + + static class ClassLevelRollbackWithExplicitValueOnTestInterfaceTestCase implements RollbackFalseTestInterface { + + public void test() { + } + } + + @Commit + interface RollbackFalseViaMetaAnnotationTestInterface { + } + + static class ClassLevelRollbackViaMetaAnnotationOnTestInterfaceTestCase + implements RollbackFalseViaMetaAnnotationTestInterface { + + public void test() { + } + } + } diff --git a/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java b/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java index 03db1d60490..3416f215f0a 100644 --- a/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * 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. @@ -25,10 +25,13 @@ import java.lang.annotation.Target; import org.junit.Test; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.util.MetaAnnotationUtils.AnnotationDescriptor; +import org.springframework.test.util.MetaAnnotationUtils.UntypedAnnotationDescriptor; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @@ -112,10 +115,27 @@ public class MetaAnnotationUtilsTests { @Test public void findAnnotationDescriptorWithInheritedAnnotationOnInterface() throws Exception { // Note: @Transactional is inherited - assertEquals(InheritedAnnotationInterface.class, - findAnnotationDescriptor(InheritedAnnotationInterface.class, Transactional.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptor(SubInheritedAnnotationInterface.class, Transactional.class)); - assertNull(findAnnotationDescriptor(SubSubInheritedAnnotationInterface.class, Transactional.class)); + Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class); + + AnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptor(InheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(InheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptor(SubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptor(SubSubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubSubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -130,9 +150,21 @@ public class MetaAnnotationUtilsTests { @Test public void findAnnotationDescriptorForNonInheritedAnnotationOnInterface() throws Exception { // Note: @Order is not inherited. - assertEquals(NonInheritedAnnotationInterface.class, - findAnnotationDescriptor(NonInheritedAnnotationInterface.class, Order.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptor(SubNonInheritedAnnotationInterface.class, Order.class)); + Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class); + + AnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptor(NonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptor(SubNonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(SubNonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -158,7 +190,17 @@ public class MetaAnnotationUtilsTests { @Test public void findAnnotationDescriptorForClassWithMetaAnnotatedInterface() { - assertNull(findAnnotationDescriptor(ClassWithMetaAnnotatedInterface.class, Component.class)); + Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, + Component.class); + + AnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptor(ClassWithMetaAnnotatedInterface.class, Component.class); + assertNotNull(descriptor); + assertEquals(ClassWithMetaAnnotatedInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(Meta1.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + assertEquals(Meta1.class, descriptor.getComposedAnnotation().annotationType()); } @Test @@ -253,11 +295,27 @@ public class MetaAnnotationUtilsTests { @SuppressWarnings("unchecked") public void findAnnotationDescriptorForTypesWithInheritedAnnotationOnInterface() throws Exception { // Note: @Transactional is inherited - assertEquals( - InheritedAnnotationInterface.class, - findAnnotationDescriptorForTypes(InheritedAnnotationInterface.class, Transactional.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptorForTypes(SubInheritedAnnotationInterface.class, Transactional.class)); - assertNull(findAnnotationDescriptorForTypes(SubSubInheritedAnnotationInterface.class, Transactional.class)); + Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class); + + UntypedAnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptorForTypes(InheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(InheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptorForTypes(SubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptorForTypes(SubSubInheritedAnnotationInterface.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(SubSubInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(InheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -274,10 +332,21 @@ public class MetaAnnotationUtilsTests { @SuppressWarnings("unchecked") public void findAnnotationDescriptorForTypesForNonInheritedAnnotationOnInterface() throws Exception { // Note: @Order is not inherited. - assertEquals( - NonInheritedAnnotationInterface.class, - findAnnotationDescriptorForTypes(NonInheritedAnnotationInterface.class, Order.class).getRootDeclaringClass()); - assertNull(findAnnotationDescriptorForTypes(SubNonInheritedAnnotationInterface.class, Order.class)); + Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class); + + UntypedAnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptorForTypes(NonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + + descriptor = findAnnotationDescriptorForTypes(SubNonInheritedAnnotationInterface.class, Order.class); + assertNotNull(descriptor); + assertEquals(SubNonInheritedAnnotationInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(NonInheritedAnnotationInterface.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); } @Test @@ -345,8 +414,18 @@ public class MetaAnnotationUtilsTests { @Test @SuppressWarnings("unchecked") public void findAnnotationDescriptorForTypesForClassWithMetaAnnotatedInterface() { - assertNull(findAnnotationDescriptorForTypes(ClassWithMetaAnnotatedInterface.class, Service.class, - Component.class, Order.class, Transactional.class)); + Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, + Component.class); + + UntypedAnnotationDescriptor descriptor; + + descriptor = findAnnotationDescriptorForTypes(ClassWithMetaAnnotatedInterface.class, Service.class, + Component.class, Order.class, Transactional.class); + assertNotNull(descriptor); + assertEquals(ClassWithMetaAnnotatedInterface.class, descriptor.getRootDeclaringClass()); + assertEquals(Meta1.class, descriptor.getDeclaringClass()); + assertEquals(rawAnnotation, descriptor.getAnnotation()); + assertEquals(Meta1.class, descriptor.getComposedAnnotation().annotationType()); } @Test