Doc. usage of JSR-250 lifecycle annotations in TCF

The reference manual previously did not mention the applicability of
JSR-250 lifecycle annotations within the TestContext framework. The
lacking documentation here has lead to misunderstandings of the support
provided for @PostConstruct and @PreDestroy in test classes.

The testing chapter of the reference manual has therefore been updated
to explicitly define the limited support for these annotations.

Also introduced Jsr250LifecycleTests for empirical verification of the 
expected behavior.

Issue: SPR-4868
This commit is contained in:
Sam Brannen 2012-05-19 04:03:40 +02:00
parent 03d6350e4b
commit e71cd06a46
3 changed files with 188 additions and 0 deletions

View File

@ -0,0 +1,118 @@
/*
* Copyright 2002-2012 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.junit4.spr4868;
import static org.junit.Assert.assertNotNull;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
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.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
/**
* Integration tests that investigate the applicability of JSR-250 lifecycle
* annotations in test classes.
*
* <p>This class does not really contain actual <em>tests</em> per se. Rather it
* can be used to empirically verify the expected log output (see below). In
* order to see the log output, one would naturally need to ensure that the
* logger category for this class is enabled at {@code INFO} level.
*
* <h4>Expected Log Output</h4>
* <pre>
* INFO : org.springframework.test.context.junit4.spr4868.LifecycleBean - initializing
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - beforeAllTests()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - setUp()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - test1()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - tearDown()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - beforeAllTests()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - setUp()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - test2()
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - tearDown()
* INFO : org.springframework.test.context.junit4.spr4868.LifecycleBean - destroying
* </pre>
*
* @author Sam Brannen
* @since 3.2
*/
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })
@ContextConfiguration
public class Jsr250LifecycleTests {
private final Log logger = LogFactory.getLog(Jsr250LifecycleTests.class);
@Configuration
static class Config {
@Bean
public LifecycleBean lifecycleBean() {
return new LifecycleBean();
}
}
@Autowired
private LifecycleBean lifecycleBean;
@PostConstruct
public void beforeAllTests() {
logger.info("beforeAllTests()");
}
@PreDestroy
public void afterTestSuite() {
logger.info("afterTestSuite()");
}
@Before
public void setUp() throws Exception {
logger.info("setUp()");
}
@After
public void tearDown() throws Exception {
logger.info("tearDown()");
}
@Test
public void test1() {
logger.info("test1()");
assertNotNull(lifecycleBean);
}
@Test
public void test2() {
logger.info("test2()");
assertNotNull(lifecycleBean);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2002-2012 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.junit4.spr4868;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Sam Brannen
* @since 3.2
*/
class LifecycleBean {
private final Log logger = LogFactory.getLog(LifecycleBean.class);
@PostConstruct
public void init() {
logger.info("initializing");
}
@PreDestroy
public void destroy() {
logger.info("destroying");
}
}

View File

@ -841,6 +841,32 @@ public void testProcessWithoutTransaction() {
</para>
</listitem>
</itemizedlist>
<note>
<title>JSR-250 Lifecycle Annotations</title>
<para>In the Spring TestContext Framework
<interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename> may be used with standard
semantics on any application components configured in the
<interfacename>ApplicationContext</interfacename>; however, these
lifecycle annotations have limited usage within an actual test
class.</para>
<para>If a method within a test class is annotated with
<interfacename>@PostConstruct</interfacename>, that method will be
executed before any <emphasis>before</emphasis> methods of the
underlying test framework (e.g., methods annotated with JUnit's
<interfacename>@Before</interfacename>), and that will apply for
every test method in the test class. On the other hand, if a method
within a test class is annotated with
<interfacename>@PreDestroy</interfacename>, that method will
<emphasis role="bold">never</emphasis> be executed. Within a test
class it is therefore recommended to use test lifecycle callbacks
from the underlying test framework instead of
<interfacename>@PostConstruct</interfacename> and
<interfacename>@PreDestroy</interfacename>.</para>
</note>
</section>
<section id="integration-testing-annotations-junit">