Commit Graph

460 Commits

Author SHA1 Message Date
Sam Brannen ea0c37a535 Polishing 2015-07-03 18:38:20 +02:00
Sam Brannen 3c4ec9026a Introduce test for DeferredResult w/ delayed error in MVC Test
This commit introduces a test that verifies the fix introduced in
6842fd7fb9.

Issue: SPR-13079
2015-07-03 17:51:46 +02:00
Sam Brannen 0e70630ac4 Polish AsyncTests 2015-07-03 17:01:21 +02:00
Sam Brannen 0aac02d649 Introduce DirtiesContextBeforeModesTestExecutionListener
SPR-12429 introduced various `BEFORE_*` modes in `@DirtiesContext`. To
support these new modes, `DirtiesContextTestExecutionListener` (DCTEL)
was updated to support both `BEFORE_*` and `AFTER_*` modes. However,
there is a problem with having DCTEL support `BEFORE_*` modes since it
is typically configured to execute after the
`DependencyInjectionTestExecutionListener` (DITEL), and this leads to
several undesired side effects:

 - The test's `ApplicationContext` is closed by DCTEL *after*
   dependencies have been injected into the test instance.

 - Injected dependencies may therefore attempt to interact with an
   `ApplicationContext` that is no longer _active_.

 - If a test has its `ApplicationContext` injected as a dependency,
   interaction with the context will likely fail since the context has
   been closed.

 - Any `TestExecutionListeners` registered after DCTEL will get a _new_
   `ApplicationContext` if they invoke `getApplicationContext()` on the
   `TestContext`.

This commit fixes these issues by introducing a new
`DirtiesContextBeforeModesTestExecutionListener` (DCBMTEL) that is
registered by default before DITEL. The previous support for `BEFORE_*`
modes has been moved from DCTEL to DCBMTEL. In addition, an
`AbstractDirtiesContextTestExecutionListener` has been extracted from
DCTEL in order to avoid code duplication.

Issue: SPR-13180
2015-07-01 20:55:12 +02:00
Sam Brannen 63a1348c32 Polish LoggingResultHandler in Spring MVC Test
Issue: SPR-13171
2015-06-27 22:44:42 +02:00
Sam Brannen 693dcba867 Introduce LoggingResultHandler in Spring MVC Test
Prior to this commit, the Spring MVC Test framework only provided
support for printing debug information about the MvcResult to STDOUT.

This commit introduces support for logging `MvcResult` details at
`DEBUG` level via the Apache Commons Logging API. In addition, this
commit introduces additional `print(..)` variants for printing debug
information to custom output streams and writers.

Specifically, `MockMvcResultHandlers` has been augmented with the
following new static methods:

 - `log()`
 - `print(OutputStream)`
 - `print(Writer)`

Issue: SPR-13171
2015-06-27 21:53:19 +02:00
Sam Brannen 895d43a2b3 Print cookies in human-readable form in Spring MVC Test
Prior to this commit, when rendering cookies via `andDo(print())` in
Spring MVC Test, the output for the `MockHttpServletResponse` would
look something like the following:

  Cookies = [javax.servlet.http.Cookie@25084a1e]

The reason is that the Cookie class in javax.servlet-api-3.0.1.jar does
not implement toString(). Consequently, nothing about the cookie's
name, value, etc., is displayed, thereby making the debug output for
cookies next to useless.

This commit improves on this by implementing custom toString() logic
for cookies in debug output in Spring MVC Test. For example, the output
now looks like this (without the newlines):

  Cookies = [[Cookie@47faa49c name = 'enigma', value = '42', \\
            comment = [null], domain = [null], maxAge = -1, \\
            path = [null], secure = false, version = 0, \\
            httpOnly = false]]

In addition, this commit fixes a minor bug for FlashMap debug output if
the FlashMap is empty.

Issue: SPR-13168
2015-06-27 02:54:42 +02:00
Juergen Hoeller a2d3c27ed1 Allow MVC handler methods to return any CharSequence type as view name
Issue: SPR-13165
2015-06-26 22:17:53 +02:00
Rossen Stoyanchev 6842fd7fb9 Ensure result ready in asyncDispatch in MockMvc
Issue: SPR-13079
2015-06-25 09:25:21 -04:00
Sam Brannen 10a691bd51 Support inlined SQL statements in @Sql
Prior to this commit, it was only possible to declare SQL statements
via @Sql within external script resources (i.e., classpath or file
system resources); however, many developers have inquired about the
ability to inline SQL statements with @Sql analogous to the support for
inlined properties in @TestPropertySource.

This commit introduces support for declaring _inlined SQL statements_
in `@Sql` via a new `statements` attribute. Inlined statements are
executed after statements in scripts.

Issue: SPR-13159
2015-06-23 20:45:00 +02:00
Sam Brannen d0c0d9fc5a Synthesize annotation from defaults
This commit introduces a convenience method in AnnotationUtils for
synthesizing an annotation from its default attribute values.

TransactionalTestExecutionListener has been refactored to invoke this
new convenience method.

Issue: SPR-13087
2015-06-20 18:27:36 +02:00
Sam Brannen 27d1ce84a3 Polishing 2015-06-20 01:45:46 +02:00
Sam Brannen fb83e83e78 Honor contract of @Repeatable in AnnotationUtils
Prior to this commit, the implementation of getRepeatableAnnotation()
in Spring's AnnotationUtils complied neither with the contract of
getAnnotationsByType() nor with the contract of
getDeclaredAnnotationsByType() as defined in AnnotatedElement in Java 8.

Specifically, unexpected results can be encountered when using Spring's
support for @Repeatable annotations: either annotations show up in the
returned set in the wrong order, or annotations are returned in the set
that should not even be found based on the semantics of @Repeatable.

This commit remedies this problem by deprecating the existing
getRepeatableAnnotation() methods and replacing them with new
getRepeatableAnnotations() and getDeclaredRepeatableAnnotations()
methods that comply with the contracts of Java's getAnnotationsByType()
and getDeclaredAnnotationsByType(), respectively.

Issue: SPR-13068
2015-06-20 01:21:39 +02:00
Sam Brannen 23547a72f3 Clean up warnings and polish tests 2015-06-19 14:57:28 +01:00
Sam Brannen 37d61375e2 Fix typo 2015-06-19 14:39:50 +01:00
Sam Brannen ece12f9d37 Synthesize annotation from map w/ minimal attributes
The initial support for synthesizing an annotation from a Map (or
AnnotationAttributes) introduced in SPR-13067 required that the map
contain key-value pairs for every attribute defined by the supplied
annotationType. However, there are use cases that would benefit from
being able to supply a reduced set of attributes and still have the
annotation synthesized properly.

This commit refines the validation mechanism in
MapAnnotationAttributeExtractor so that a reduced set of attributes may
be supplied. Specifically, if an attribute is missing in the supplied
map the attribute will be set either to value of its alias (if an alias
value configured via @AliasFor exists) or to the value of the
attribute's default value (if defined), and otherwise an exception will
be thrown.

Furthermore, TransactionalTestExecutionListener has been refactored to
take advantage of this new feature by synthesizing an instance of
@TransactionConfiguration solely from the default values of its
declared attributes.

Issue: SPR-13087
2015-06-19 14:27:23 +01:00
Brian Clozel f988151163 Improve charset management in XpathResultMatchers
Prior to this change, `XpathResultMatchers` and more generally the
`MockHttpServletResponse` would default to ISO-8859-1 encoding even when
it's not supposed to. The Servlet/HTTP specs mention this encoding
for all `text/*` mime types when decoding bodies to Strings, but this
issue is about XML Parsers.

XML Parsers should use the encoding:

* defined in the `Content-Type` response header (if available)
* written in the XML declaration of the document
* "guessed" by a built-in auto-detection mechanism

This commit changes the following:

* XPathMatchers now feed the XML parser with byte arrays instead of
decoded Strings
* the response should be written to `MockHttpServletResponse` using
its OutputStream, and not a PrintWriter which defaults to ISO-8859-1

Issue: SPR-12676
2015-06-17 10:09:54 +02:00
Sam Brannen 68a704373d Retain order of active profiles in the TCF
Ever since @ActiveProfiles was introduced, the declared active profiles
for integration tests have been sorted in order to support unique cache
key generation; however, there are use cases for which the original
ordering should be retained.

For example, Spring Boot's ConfigFileApplicationListener loads
configuration files for active profiles in the order returned by
Environment.getActiveProfiles(), with the assumption that the ordering
matches the order in which the developer declared the active profiles.

This commit maintains the uniqueness of active profiles declared via
@ActiveProfiles but no longer sorts them.

Issue: SPR-12492
2015-06-15 14:25:06 +01:00
Sam Brannen ea9d7aa337 Polish Javadoc for @TransactionConfiguration 2015-06-14 15:24:20 +02:00
Sam Brannen 32c17bf540 Revise method and parameter names in annotation support
In AnnotatedElementUtils, all methods pertaining to merging annotation
attributes have been renamed to "getMerged*()" and "findMerged*()"
accordingly. Existing methods such as getAnnotationAttributes(..) have
been deprecated in favor of the more descriptive "merged" variants.
This aligns the naming conventions in AnnotatedElementUtils with those
already present in AnnotationReadingVisitorUtils.

The use of "annotationType" as a variable name for the fully qualified
class name of an annotation type has been replaced with
"annotationName" in order to improve the readability and intent of the
code base.

In MetaAnnotationUtils.AnnotationDescriptor, getMergedAnnotation() has
been renamed to synthesizeAnnotation(), and the method is now
overridden in UntypedAnnotationDescriptor to always throw an
UnsupportedOperationException in order to avoid potential run-time
ClassCastExceptions.

Issue: SPR-11511
2015-06-14 00:34:40 +02:00
Sam Brannen 6b7c1d72e8 Introduce alias for 'value' attribute in @Transactional
Issue: SPR-11393
2015-06-12 22:35:20 +02:00
Sam Brannen f6d2fe471a Proper support for Root WAC in Spring MVC Test
The modifications to DefaultMockMvcBuilder performed in conjunction
with SPR-12553 introduced a breaking change: the WebApplicationContext
supplied to DefaultMockMvcBuilder's constructor was *always* stored in
the ServletContext as the root WebApplicationContext, overwriting a
root WebApplicationContext that had been set by the user or by the
Spring TestContext Framework (TCF) -- for example, in
AbstractGenericWebContextLoader. Consequently, the changes in SPR-12553
cause tests that use @ContextHierarchy to fail if web components rely
on the correct WebApplicationContext being stored under the
WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key.

This commit reverts the breaking changes introduced in SPR-12553: if
the root WebApplicationContext has already been set in the
ServletContext of the WebApplicationContext supplied to
DefaultMockMvcBuilder, no action is taken.

Furthermore, this commit introduces new code to address the initial
intent of SPR-12553. Specifically, if the root WebApplicationContext
has NOT been set in the ServletContext of the WebApplicationContext
supplied to DefaultMockMvcBuilder, the application context hierarchy
will be traversed in search of the root WebApplicationContext, and the
root WebApplicationContext will then be stored under the
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE key.

Issue: SPR-13075, SPR-12553
2015-06-11 19:54:25 +02:00
Brian Clozel e2c8d3762f Fix tests for SPR-13090 2015-06-11 16:34:33 +02:00
Esko Luontola 89c1674b89 Fix missing space in assertion message 2015-06-01 10:56:53 -04:00
Sam Brannen 6a5b2672e7 Introduce alias for 'value' attribute in @ResponseStatus
Issue: SPR-11393
2015-05-31 17:00:23 +02:00
Sam Brannen 8f233786ed Polishing 2015-05-29 02:05:44 +02:00
Sam Brannen e30c9b2ef3 Synthesize annotation from a map of attributes
Spring Framework 4.2 RC1 introduced support for synthesizing an
annotation from an existing annotation in order to provide additional
functionality above and beyond that provided by Java. Specifically,
such synthesized annotations provide support for @AliasFor semantics.
As luck would have it, the same principle can be used to synthesize an
annotation from any map of attributes, and in particular, from an
instance of AnnotationAttributes.

The following highlight the major changes in this commit toward
achieving this goal.

- Introduced AnnotationAttributeExtractor abstraction and refactored
  SynthesizedAnnotationInvocationHandler to delegate to an
  AnnotationAttributeExtractor.

- Extracted code from SynthesizedAnnotationInvocationHandler into new
  AbstractAliasAwareAnnotationAttributeExtractor and
  DefaultAnnotationAttributeExtractor implementation classes.

- Introduced MapAnnotationAttributeExtractor for synthesizing an
  annotation that is backed by a map or AnnotationAttributes instance.

- Introduced a variant of synthesizeAnnotation() in AnnotationUtils
  that accepts a map.

- Introduced findAnnotation(*) methods in AnnotatedElementUtils that
  synthesize merged AnnotationAttributes back into an annotation of the
  target type.

The following classes have been refactored to use the new support for
synthesizing AnnotationAttributes back into an annotation.

- ApplicationListenerMethodAdapter
- TestAnnotationUtils
- AbstractTestContextBootstrapper
- ActiveProfilesUtils
- ContextLoaderUtils
- DefaultActiveProfilesResolver
- DirtiesContextTestExecutionListener
- TestPropertySourceAttributes
- TestPropertySourceUtils
- TransactionalTestExecutionListener
- MetaAnnotationUtils
- MvcUriComponentsBuilder
- RequestMappingHandlerMapping

In addition, this commit also includes changes to ensure that arrays
returned by synthesized annotations are properly cloned first.

Issue: SPR-13067
2015-05-29 01:38:51 +02:00
Sam Brannen ca66e076d1 Support annotation attribute aliases and overrides via @AliasFor
This commit introduces first-class support for aliases for annotation
attributes. Specifically, this commit introduces a new @AliasFor
annotation that can be used to declare a pair of aliased attributes
within a single annotation or an alias from an attribute in a custom
composed annotation to an attribute in a meta-annotation.

To support @AliasFor within annotation instances, AnnotationUtils has
been overhauled to "synthesize" any annotations returned by "get" and
"find" searches. A SynthesizedAnnotation is an annotation that is
wrapped in a JDK dynamic proxy which provides run-time support for
@AliasFor semantics. SynthesizedAnnotationInvocationHandler is the
actual handler behind the proxy.

In addition, the contract for @AliasFor is fully validated, and an
AnnotationConfigurationException is thrown in case invalid
configuration is detected.

For example, @ContextConfiguration from the spring-test module is now
declared as follows:

    public @interface ContextConfiguration {

        @AliasFor(attribute = "locations")
        String[] value() default {};

        @AliasFor(attribute = "value")
        String[] locations() default {};

        // ...
    }

The following annotations and their related support classes have been
modified to use @AliasFor.

- @ManagedResource
- @ContextConfiguration
- @ActiveProfiles
- @TestExecutionListeners
- @TestPropertySource
- @Sql
- @ControllerAdvice
- @RequestMapping

Similarly, support for AnnotationAttributes has been reworked to
support @AliasFor as well. This allows for fine-grained control over
exactly which attributes are overridden within an annotation hierarchy.
In fact, it is now possible to declare an alias for the 'value'
attribute of a meta-annotation.

For example, given the revised declaration of @ContextConfiguration
above, one can now develop a composed annotation with a custom
attribute override as follows.

    @ContextConfiguration
    public @interface MyTestConfig {

        @AliasFor(
           annotation = ContextConfiguration.class,
           attribute = "locations"
        )
        String[] xmlFiles();

        // ...
    }

Consequently, the following are functionally equivalent.

- @MyTestConfig(xmlFiles = "test.xml")
- @ContextConfiguration("test.xml")
- @ContextConfiguration(locations = "test.xml").

Issue: SPR-11512, SPR-11513
2015-05-22 00:01:07 +02:00
Juergen Hoeller b4095c3e1d Class identity comparisons wherever possible
Issue: SPR-12926
2015-05-20 14:34:16 +02:00
Stephane Nicoll cf391f5ce1 polish
Remove unused imports
2015-05-19 08:49:01 +02:00
Sam Brannen 428499a384 Introduce SpringFailOnTimeout(Statement, Method) constructor 2015-05-18 00:43:41 +02:00
Sam Brannen f13f493551 Introduce TestAnnotationUtils to reduce code duplication 2015-05-17 22:24:29 +02:00
Sam Brannen 973582e7df Introduce TestContextManager cache in SpringClassRule
In order to simplify configuration of the SpringMethodRule and to ensure
that the correct TestContextManager is always retrieved for the
currently executing test class, this commit introduces a static
TestContextManager cache in SpringClassRule.

In addition, since it is not foreseen that SpringClassRule and
SpringMethodRule should be able to be subclassed, their internal methods
are now private instead of protected.

Issue: SPR-7731
2015-05-17 17:14:09 +02:00
Sam Brannen 68322fc42a Introduce JUnitTestingUtils to reduce code duplication 2015-05-17 15:47:39 +02:00
Sam Brannen d1b1c4f888 Introduce JUnit Rule alternative to SpringJUnit4ClassRunner
Since Spring Framework 2.5, support for integrating the Spring
TestContext Framework (TCF) into JUnit 4 based tests has been provided
via the SpringJUnit4ClassRunner, but this approach precludes the
ability for tests to be run with alternative runners like JUnit's
Parameterized or third-party runners such as the MockitoJUnitRunner.

This commit remedies this situation by introducing @ClassRule and @Rule
based alternatives to the SpringJUnit4ClassRunner. These rules are
independent of any Runner and can therefore be combined with
alternative runners.

Due to the limitations of JUnit's implementation of rules, as of JUnit
4.12 it is currently impossible to create a single rule that can be
applied both at the class level and at the method level (with access to
the test instance). Consequently, this commit introduces the following
two rules that must be used together.

 - SpringClassRule: a JUnit TestRule that provides the class-level
   functionality of the TCF to JUnit-based tests

 - SpringMethodRule: a JUnit MethodRule that provides the
   instance-level and method-level functionality of the TCF to
   JUnit-based tests

In addition, this commit also introduces the following new JUnit
Statements for use with rules:

 - RunPrepareTestInstanceCallbacks

 - ProfileValueChecker

Issue: SPR-7731
2015-05-16 20:25:12 +02:00
Sam Brannen bccd59e6c8 Use findAnnotationAttributes() where appropriate
This commit updates code that previously used getAnnotationAttributes()
in AnnotatedElementUtils to use findAnnotationAttributes(), where
appropriate.

Issue: SPR-12738
2015-05-14 03:49:59 +02:00
Sam Brannen 6422f7a0a1 Add TODO re: FailOnTimeout.builder() & JUnit 4.12 2015-05-11 18:13:45 +02:00
Sam Brannen d14e29a5c0 Polish SpringJUnit4ClassRunner and related support classes 2015-05-11 13:39:22 +02:00
Sam Brannen cf51f0c0aa Assert pre-conditions in AopTestUtils
Issue: SPR-13005
2015-05-09 21:02:40 +02:00
Sam Brannen efe3a35da8 Introduce AOP testing utilities
This commit introduces support in the spring-test module for obtaining a
reference to the underlying target object hidden behind one or more
proxies.

Specifically this commit introduces AopTestUtils with two methods:

 - getTargetObject(Object)

 - getUltimateTargetObject(Object)

Issue: SPR-13005
2015-05-09 20:32:28 +02:00
Sam Brannen 7a690df925 Remove trailing whitespace from Java source code 2015-05-06 20:08:42 +02:00
Sam Brannen 572cbb0821 Consistently supply test name to @Parameters 2015-05-05 14:07:00 +02:00
Sam Brannen e85e9768c5 Fail if multiple @BootstrapWith's are present
Prior to this commit it was possible for two @BootstrapWith annotations
to be 'present' on a test class -- for example, via competing custom
composed annotations. However, only one of the annotations will ever be
used to bootstrap the TestContext Framework. Thus, in such scenarios
one of the annotations will be silently ignored.

This commit introduces a check for such scenarios. BootstrapUtils'
resolveTestContextBootstrapper() method now throws an
IllegalStateException if more than one @BootstrapWith annotation is
'present' on a given test class.

Issue: SPR-12602
2015-04-26 02:58:07 +02:00
Rob Winch 1a6aeb17e1 Add merged RequestPostProcessor to front on merge
Previously MockHttpServletRequestBuilder merge method would append the
parent's (default) RequestPostProcessor implementations to the end. This
means that the default RequestPostProcessor implementations would override
values set by previous RequestPostProcessor implementations.

This commit ensures that the default RequestPostProcessor are preformed
first so that additional RequestPostProcessor implementations override
the defaults.

Issue: SPR-12945
2015-04-24 13:12:29 -04:00
Sam Brannen ad6bea1cda Support abstract, bridge, & interface methods in AnnotatedElementUtils
This commit introduces support for finding annotations on abstract,
bridge, and interface methods in AnnotatedElementUtils.

 - Introduced dedicated findAnnotationAttributes() methods in
   AnnotatedElementUtils that provide first-class support for
   processing methods, class hierarchies, interfaces, bridge methods,
   etc.

 - Introduced find/get search algorithm dichotomy in
   AnnotatedElementUtils which is visible in the public API as well as
   in the internal implementation. This was necessary in order to
   maintain backwards compatibility with the existing API (even though
   it was undocumented).

 - Reverted all recent changes made to the "get semantics" search
   algorithm in AnnotatedElementUtils in order to ensure backwards
   compatibility, and reverted recent changes to
   JtaTransactionAnnotationParser and SpringTransactionAnnotationParser
   accordingly.

 - Documented internal AnnotatedElementUtils.Processor<T> interface.

 - Enabled failing tests and introduced
   findAnnotationAttributesFromBridgeMethod() test in
   AnnotatedElementUtilsTests.

 - Refactored ApplicationListenerMethodAdapter.getCondition() and
   enabled failing test in TransactionalEventListenerTests.

 - AnnotationUtils.isInterfaceWithAnnotatedMethods() is now package
   private.

Issue: SPR-12738, SPR-11514, SPR-11598
2015-04-24 00:55:48 +02:00
Sam Brannen 69b0791926 Favor local, composed annotations in the TCF
Prior to this commit, AnnotationAttributes retrieved from
MetaAnnotationUtils's AnnotationDescriptor could contain attributes
from the wrong annotation if an inherited annotation shadowed a locally
declared composed annotation.

This commit addresses this issue by invoking the new
getAnnotationAttributes() method in AnnotatedElementUtils that provides
a flag to control whether superclasses should be searched -- which
coincidentally processes local annotations before searching the class
hierarchy.

Issue: SPR-12749, SPR-11598
2015-04-23 02:44:21 +02:00
Sam Brannen 5cbe4b948d Introduce dedicated 'cache' subpackage in the TCF
Since the ContextCache is now a published SPI, it and its collaborators
have been moved to a dedicated 'org.sfw.test.context.cache' subpackage.

Issue: SPR-12683
2015-04-20 21:48:30 +02:00
Sebastien Deleuze 5b0a0f4db5 Support CompletableFuture as alternative to DeferredResult in MVC
Issue: SPR-12597
2015-04-20 14:19:31 +02:00
Sam Brannen e829b2aa1d Polish Javadoc for ContextCache 2015-04-20 00:53:45 +02:00
Sam Brannen 93f403cbf6 Ensure that contexts loaded by the TCF are active
This commit adds an assertion to DefaultTestContext's
getApplicationContext() method to ensure that a context loaded by the
Spring TestContext Framework (TCF) or retrieved from the ContextCache
is still active. This extra check helps to avoid situations where
developers manually close a cached context instead of relying on the
@DirtiesContext support.

Issue: SPR-12932
2015-04-20 00:37:16 +02:00