Browse Source

Support test annotations on interfaces

Prior to Java 8 it never really made much sense to author integration
tests using interfaces. Consequently, the Spring TestContext Framework
has never supported finding test-related annotations on interfaces in
its search algorithms.

However, Java 8's support for interface default methods introduces new
testing use cases for which it makes sense to declare test
configuration (e.g., @ContextConfiguration, etc.) on an interface
containing default methods instead of on an abstract base class.

This commit ensures that all non-repeatable, class-level test
annotations in the Spring TestContext Framework can now be declared on
test interfaces. The only test annotations that cannot be declared on
interfaces are therefore @Sql and @SqlGroup.

Issue: SPR-14184
pull/1050/head
Sam Brannen 10 years ago
parent
commit
a1a87679da
  1. 9
      spring-context/src/test/java/org/springframework/tests/sample/beans/Employee.java
  2. 4
      spring-test/src/main/java/org/springframework/test/annotation/Commit.java
  3. 10
      spring-test/src/main/java/org/springframework/test/annotation/ProfileValueSourceConfiguration.java
  4. 2
      spring-test/src/main/java/org/springframework/test/annotation/Rollback.java
  5. 4
      spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java
  6. 24
      spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java
  7. 6
      spring-test/src/main/java/org/springframework/test/context/BootstrapWith.java
  8. 6
      spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java
  9. 6
      spring-test/src/main/java/org/springframework/test/context/ContextHierarchy.java
  10. 4
      spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java
  11. 4
      spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java
  12. 43
      spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java
  13. 28
      spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java
  14. 13
      spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java
  15. 17
      spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java
  16. 65
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java
  17. 27
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java
  18. 43
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java
  19. 47
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java
  20. 45
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java
  21. 39
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java
  22. 58
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java
  23. 31
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java
  24. 95
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java
  25. 27
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java
  26. 46
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java
  27. 32
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java
  28. 57
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java
  29. 27
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java
  30. 44
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java
  31. 37
      spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java
  32. 6
      spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java
  33. 32
      spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java
  34. 119
      spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java

9
spring-context/src/test/java/org/springframework/tests/sample/beans/Employee.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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;
}

4
spring-test/src/main/java/org/springframework/test/annotation/Commit.java

@ -1,5 +1,5 @@ @@ -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; @@ -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; @@ -51,6 +52,7 @@ import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Rollback(false)
public @interface Commit {
}

10
spring-test/src/main/java/org/springframework/test/annotation/ProfileValueSourceConfiguration.java

@ -1,5 +1,5 @@ @@ -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; @@ -24,7 +24,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* <p>{@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 <em>profile values</em> configured via the {@link IfProfileValue
* &#064;IfProfileValue} annotation.
@ -38,17 +38,15 @@ import java.lang.annotation.Target; @@ -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 {
/**
* <p>
* The type of {@link ProfileValueSource} to use when retrieving
* <em>profile values</em>.
* </p>
*
* @see SystemProfileValueSource
*/

2
spring-test/src/main/java/org/springframework/test/annotation/Rollback.java

@ -18,6 +18,7 @@ package org.springframework.test.annotation; @@ -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; @@ -56,6 +57,7 @@ import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Rollback {
/**

4
spring-test/src/main/java/org/springframework/test/context/ActiveProfiles.java

@ -43,10 +43,10 @@ import org.springframework.core.annotation.AliasFor; @@ -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 {
/**

24
spring-test/src/main/java/org/springframework/test/context/BootstrapUtils.java

@ -17,16 +17,15 @@ @@ -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 { @@ -151,17 +150,16 @@ abstract class BootstrapUtils {
* @since 4.3
*/
private static Class<?> resolveExplicitTestContextBootstrapper(Class<?> testClass) {
MultiValueMap<String, Object> attributesMultiMap =
AnnotatedElementUtils.getAllAnnotationAttributes(testClass, BootstrapWith.class.getName());
List<Object> values = (attributesMultiMap != null ? attributesMultiMap.get(AnnotationUtils.VALUE) : null);
if (values == null) {
Set<BootstrapWith> 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 { @@ -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);

6
spring-test/src/main/java/org/springframework/test/context/BootstrapWith.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 {
/**

6
spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 {
/**

6
spring-test/src/main/java/org/springframework/test/context/ContextHierarchy.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 {
/**

4
spring-test/src/main/java/org/springframework/test/context/TestExecutionListeners.java

@ -42,10 +42,10 @@ import org.springframework.core.annotation.AliasFor; @@ -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 {
/**

4
spring-test/src/main/java/org/springframework/test/context/TestPropertySource.java

@ -82,10 +82,10 @@ import org.springframework.core.annotation.AliasFor; @@ -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 {
/**

43
spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java

@ -57,8 +57,8 @@ public abstract class MetaAnnotationUtils { @@ -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.
* <p>This method explicitly handles class-level annotations which are not
* declared as {@linkplain java.lang.annotation.Inherited inherited} <em>as
* well as meta-annotations</em>.
@ -67,14 +67,12 @@ public abstract class MetaAnnotationUtils { @@ -67,14 +67,12 @@ public abstract class MetaAnnotationUtils {
* <li>Search for the annotation on the given class and return a corresponding
* {@code AnnotationDescriptor} if found.
* <li>Recursively search through all annotations that the given class declares.
* <li>Recursively search through all interfaces implemented by the given class.
* <li>Recursively search through the superclass hierarchy of the given class.
* </ol>
* <p>In this context, the term <em>recursively</em> 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.
* <p>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 { @@ -123,6 +121,15 @@ public abstract class MetaAnnotationUtils {
}
}
// Declared on interface?
for (Class<?> ifc : clazz.getInterfaces()) {
AnnotationDescriptor<T> descriptor = findAnnotationDescriptor(ifc, visited, annotationType);
if (descriptor != null) {
return new AnnotationDescriptor<T>(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 { @@ -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}.
* <p>This method traverses the annotations and superclasses of the specified
* {@code clazz} if no annotation can be found on the given class itself.
* <p>This method traverses the annotations, interfaces, and superclasses
* of the specified {@code clazz} if no annotation can be found on the given
* class itself.
* <p>This method explicitly handles class-level annotations which are not
* declared as {@linkplain java.lang.annotation.Inherited inherited} <em>as
* well as meta-annotations</em>.
@ -143,14 +151,12 @@ public abstract class MetaAnnotationUtils { @@ -143,14 +151,12 @@ public abstract class MetaAnnotationUtils {
* the given class and return a corresponding {@code UntypedAnnotationDescriptor}
* if found.
* <li>Recursively search through all annotations that the given class declares.
* <li>Recursively search through all interfaces implemented by the given class.
* <li>Recursively search through the superclass hierarchy of the given class.
* </ol>
* <p>In this context, the term <em>recursively</em> 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.
* <p>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 { @@ -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);
}

28
spring-test/src/test/java/org/springframework/test/annotation/ProfileValueUtilsTests.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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 {
}
}

13
spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java

@ -115,6 +115,12 @@ public class TestExecutionListenersTests { @@ -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 { @@ -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 {
}

17
spring-test/src/test/java/org/springframework/test/context/cache/ClassLevelDirtiesContextTests.java vendored

@ -1,5 +1,5 @@ @@ -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; @@ -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.*; @@ -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 { @@ -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 {

65
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesInterfaceTests.java

@ -0,0 +1,65 @@ @@ -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");
}
}
}

27
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ActiveProfilesTestInterface.java

@ -0,0 +1,27 @@ @@ -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 {
}

43
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithInterfaceTests.java

@ -0,0 +1,43 @@ @@ -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);
}
}

47
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/BootstrapWithTestInterface.java

@ -0,0 +1,47 @@ @@ -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<ContextCustomizerFactory> getContextCustomizerFactories() {
return singletonList(
(ContextCustomizerFactory) (testClass, configAttributes) -> (ContextCustomizer) (context,
mergedConfig) -> context.getBeanFactory().registerSingleton("foo", "foo"));
}
}
}

45
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationInterfaceTests.java

@ -0,0 +1,45 @@ @@ -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());
}
}

39
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextConfigurationTestInterface.java

@ -0,0 +1,39 @@ @@ -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");
}
}
}

58
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyInterfaceTests.java

@ -0,0 +1,58 @@ @@ -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);
}
}

31
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/ContextHierarchyTestInterface.java

@ -0,0 +1,31 @@ @@ -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 {
}

95
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextInterfaceTests.java

@ -0,0 +1,95 @@ @@ -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 */
}
}
}

27
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/DirtiesContextTestInterface.java

@ -0,0 +1,27 @@ @@ -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 {
}

46
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigInterfaceTests.java

@ -0,0 +1,46 @@ @@ -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"));
}
}

32
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/SqlConfigTestInterface.java

@ -0,0 +1,32 @@ @@ -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 {
}

57
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceInterfaceTests.java

@ -0,0 +1,57 @@ @@ -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 */
}
}

27
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/TestPropertySourceTestInterface.java

@ -0,0 +1,27 @@ @@ -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 {
}

44
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationInterfaceTests.java

@ -0,0 +1,44 @@ @@ -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);
}
}

37
spring-test/src/test/java/org/springframework/test/context/configuration/interfaces/WebAppConfigurationTestInterface.java

@ -0,0 +1,37 @@ @@ -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 */
}
}

6
spring-test/src/test/java/org/springframework/test/context/hierarchies/standard/SingleTestClassWithTwoLevelContextHierarchyTests.java

@ -1,5 +1,5 @@ @@ -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.*; @@ -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 { @@ -54,7 +54,7 @@ public class SingleTestClassWithTwoLevelContextHierarchyTests {
}
@Configuration
static class ChildConfig {
public static class ChildConfig {
@Bean
public String bar() {

32
spring-test/src/test/java/org/springframework/test/context/transaction/TransactionalTestExecutionListenerTests.java

@ -54,6 +54,7 @@ public class TransactionalTestExecutionListenerTests { @@ -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 { @@ -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 { @@ -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() {
}
}
}

119
spring-test/src/test/java/org/springframework/test/util/MetaAnnotationUtilsTests.java

@ -1,5 +1,5 @@ @@ -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; @@ -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 { @@ -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<Transactional> 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 { @@ -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<Order> 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 { @@ -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<Component> 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 { @@ -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 { @@ -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 { @@ -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

Loading…
Cancel
Save