Skip to content

Commit e71cd06

Browse files
committed
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
1 parent 03d6350 commit e71cd06

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.junit4.spr4868;
18+
19+
import static org.junit.Assert.assertNotNull;
20+
21+
import javax.annotation.PostConstruct;
22+
import javax.annotation.PreDestroy;
23+
24+
import org.apache.commons.logging.Log;
25+
import org.apache.commons.logging.LogFactory;
26+
import org.junit.After;
27+
import org.junit.Before;
28+
import org.junit.Test;
29+
import org.junit.runner.RunWith;
30+
import org.springframework.beans.factory.annotation.Autowired;
31+
import org.springframework.context.annotation.Bean;
32+
import org.springframework.context.annotation.Configuration;
33+
import org.springframework.test.context.ContextConfiguration;
34+
import org.springframework.test.context.TestExecutionListeners;
35+
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
36+
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
37+
38+
/**
39+
* Integration tests that investigate the applicability of JSR-250 lifecycle
40+
* annotations in test classes.
41+
*
42+
* <p>This class does not really contain actual <em>tests</em> per se. Rather it
43+
* can be used to empirically verify the expected log output (see below). In
44+
* order to see the log output, one would naturally need to ensure that the
45+
* logger category for this class is enabled at {@code INFO} level.
46+
*
47+
* <h4>Expected Log Output</h4>
48+
* <pre>
49+
* INFO : org.springframework.test.context.junit4.spr4868.LifecycleBean - initializing
50+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - beforeAllTests()
51+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - setUp()
52+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - test1()
53+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - tearDown()
54+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - beforeAllTests()
55+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - setUp()
56+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - test2()
57+
* INFO : org.springframework.test.context.junit4.spr4868.ExampleTest - tearDown()
58+
* INFO : org.springframework.test.context.junit4.spr4868.LifecycleBean - destroying
59+
* </pre>
60+
*
61+
* @author Sam Brannen
62+
* @since 3.2
63+
*/
64+
@RunWith(SpringJUnit4ClassRunner.class)
65+
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class })
66+
@ContextConfiguration
67+
public class Jsr250LifecycleTests {
68+
69+
private final Log logger = LogFactory.getLog(Jsr250LifecycleTests.class);
70+
71+
72+
@Configuration
73+
static class Config {
74+
75+
@Bean
76+
public LifecycleBean lifecycleBean() {
77+
return new LifecycleBean();
78+
}
79+
}
80+
81+
82+
@Autowired
83+
private LifecycleBean lifecycleBean;
84+
85+
86+
@PostConstruct
87+
public void beforeAllTests() {
88+
logger.info("beforeAllTests()");
89+
}
90+
91+
@PreDestroy
92+
public void afterTestSuite() {
93+
logger.info("afterTestSuite()");
94+
}
95+
96+
@Before
97+
public void setUp() throws Exception {
98+
logger.info("setUp()");
99+
}
100+
101+
@After
102+
public void tearDown() throws Exception {
103+
logger.info("tearDown()");
104+
}
105+
106+
@Test
107+
public void test1() {
108+
logger.info("test1()");
109+
assertNotNull(lifecycleBean);
110+
}
111+
112+
@Test
113+
public void test2() {
114+
logger.info("test2()");
115+
assertNotNull(lifecycleBean);
116+
}
117+
118+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2002-2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.test.context.junit4.spr4868;
18+
19+
import javax.annotation.PostConstruct;
20+
import javax.annotation.PreDestroy;
21+
22+
import org.apache.commons.logging.Log;
23+
import org.apache.commons.logging.LogFactory;
24+
25+
/**
26+
* @author Sam Brannen
27+
* @since 3.2
28+
*/
29+
class LifecycleBean {
30+
31+
private final Log logger = LogFactory.getLog(LifecycleBean.class);
32+
33+
34+
@PostConstruct
35+
public void init() {
36+
logger.info("initializing");
37+
}
38+
39+
@PreDestroy
40+
public void destroy() {
41+
logger.info("destroying");
42+
}
43+
44+
}

src/reference/docbook/testing.xml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,32 @@ public void testProcessWithoutTransaction() {
841841
</para>
842842
</listitem>
843843
</itemizedlist>
844+
845+
<note>
846+
<title>JSR-250 Lifecycle Annotations</title>
847+
848+
<para>In the Spring TestContext Framework
849+
<interfacename>@PostConstruct</interfacename> and
850+
<interfacename>@PreDestroy</interfacename> may be used with standard
851+
semantics on any application components configured in the
852+
<interfacename>ApplicationContext</interfacename>; however, these
853+
lifecycle annotations have limited usage within an actual test
854+
class.</para>
855+
856+
<para>If a method within a test class is annotated with
857+
<interfacename>@PostConstruct</interfacename>, that method will be
858+
executed before any <emphasis>before</emphasis> methods of the
859+
underlying test framework (e.g., methods annotated with JUnit's
860+
<interfacename>@Before</interfacename>), and that will apply for
861+
every test method in the test class. On the other hand, if a method
862+
within a test class is annotated with
863+
<interfacename>@PreDestroy</interfacename>, that method will
864+
<emphasis role="bold">never</emphasis> be executed. Within a test
865+
class it is therefore recommended to use test lifecycle callbacks
866+
from the underlying test framework instead of
867+
<interfacename>@PostConstruct</interfacename> and
868+
<interfacename>@PreDestroy</interfacename>.</para>
869+
</note>
844870
</section>
845871

846872
<section id="integration-testing-annotations-junit">

0 commit comments

Comments
 (0)