Skip to content

Commit 027c25d

Browse files
committed
[SPR-8401] Documented TestContext support for @activeprofiles in the reference manual.
1 parent e172197 commit 027c25d

File tree

1 file changed

+192
-12
lines changed

1 file changed

+192
-12
lines changed

spring-framework-reference/src/testing.xml

Lines changed: 192 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,7 @@ public void testProcessRepeatedly() {
10591059
</section>
10601060

10611061
<section id="testcontext-ctx-management">
1062-
<title>Context management and caching</title>
1062+
<title>Context management</title>
10631063

10641064
<para>Each <classname>TestContext</classname> provides context
10651065
management and caching support for the test instance it is responsible
@@ -1267,14 +1267,15 @@ public class OrderServiceTest {
12671267
linkend="integration-testing-annotations-spring" /> the TestContext
12681268
framework does not allow you to declare <emphasis>both</emphasis>
12691269
via <interfacename>@ContextConfiguration</interfacename>, but this
1270-
does not mean that you cannot use both. If you want to use XML
1271-
<emphasis role="bold">and</emphasis>
1270+
does not mean that you cannot use both.</para>
1271+
1272+
<para>If you want to use XML <emphasis role="bold">and</emphasis>
12721273
<interfacename>@Configuration</interfacename> classes to configure
12731274
your tests, you will have to pick one as the <emphasis>entry
12741275
point</emphasis>, and that one will have to include or import the
12751276
other. For example, in XML you can include
1276-
<interfacename>@Configuration</interfacename> classes in component
1277-
scanning or define them as normal Spring beans; whereas, in a
1277+
<interfacename>@Configuration</interfacename> classes via component
1278+
scanning or define them as normal Spring beans in XML; whereas, in a
12781279
<interfacename>@Configuration</interfacename> class you can use
12791280
<interfacename>@ImportResource</interfacename> to import XML
12801281
configuration files. Note that this behavior is semantically
@@ -1283,8 +1284,8 @@ public class OrderServiceTest {
12831284
resource locations or a set of
12841285
<interfacename>@Configuration</interfacename> classes that your
12851286
production <interfacename>ApplicationContext</interfacename> will
1286-
load, but you still have the freedom to include or import the other
1287-
type of configuration.</para>
1287+
loaded from, but you still have the freedom to include or import the
1288+
other type of configuration.</para>
12881289
</section>
12891290

12901291
<section id="testcontext-ctx-management-inheritance">
@@ -1357,18 +1358,197 @@ public class ExtendedTest extends BaseTest {
13571358
}</programlisting>
13581359
</section>
13591360

1361+
<section id="testcontext-ctx-management-env-profiles">
1362+
<title>Context configuration with environment profiles</title>
1363+
1364+
<para>Spring 3.1 introduces first-class support in the framework for
1365+
the notion of environments and profiles (a.k.a., bean definition
1366+
profiles), and integration tests can now be configured to activate
1367+
particular bean definition profiles for various testing scenarios.
1368+
This is achieved by annotating a test class with the new
1369+
@ActiveProfiles annotation and supplying a list of profiles that
1370+
should be activated when loading the ApplicationContext for the
1371+
test.</para>
1372+
1373+
<note>
1374+
<para>@ActiveProfiles may be used with any implementation of the
1375+
new SmartContextLoader SPI, but @ActiveProfiles is not supported
1376+
with implementations of the older ContextLoader SPI.</para>
1377+
</note>
1378+
1379+
<para>Let's take a look at some examples with XML configuration and
1380+
@Configuration classes.</para>
1381+
1382+
<programlisting language="xml">&lt;!-- app-config.xml --&gt;
1383+
&lt;beans xmlns="http://www.springframework.org/schema/beans"
1384+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1385+
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
1386+
xmlns:jee="http://www.springframework.org/schema/jee"
1387+
xsi:schemaLocation="..."&gt;
1388+
1389+
&lt;bean id="transferService"
1390+
class="com.bank.service.internal.DefaultTransferService"&gt;
1391+
&lt;constructor-arg ref="accountRepository"/&gt;
1392+
&lt;constructor-arg ref="feePolicy"/&gt;
1393+
&lt;/bean&gt;
1394+
1395+
&lt;bean id="accountRepository"
1396+
class="com.bank.repository.internal.JdbcAccountRepository"&gt;
1397+
&lt;constructor-arg ref="dataSource"/&gt;
1398+
&lt;/bean&gt;
1399+
1400+
&lt;bean id="feePolicy"
1401+
class="com.bank.service.internal.ZeroFeePolicy"/&gt;
1402+
1403+
&lt;beans profile="dev"&gt;
1404+
&lt;jdbc:embedded-database id="dataSource"&gt;
1405+
&lt;jdbc:script
1406+
location="classpath:com/bank/config/sql/schema.sql"/&gt;
1407+
&lt;jdbc:script
1408+
location="classpath:com/bank/config/sql/test-data.sql"/&gt;
1409+
&lt;/jdbc:embedded-database&gt;
1410+
&lt;/beans&gt;
1411+
1412+
&lt;beans profile="production"&gt;
1413+
&lt;jee:jndi-lookup id="dataSource"
1414+
jndi-name="java:comp/env/jdbc/datasource"/&gt;
1415+
&lt;/beans&gt;
1416+
1417+
&lt;/beans&gt;</programlisting>
1418+
1419+
<programlisting language="java">package com.bank.service;
1420+
1421+
@RunWith(SpringJUnit4ClassRunner.class)
1422+
// ApplicationContext will be loaded from "classpath:/app-config.xml"
1423+
@ContextConfiguration("/app-config.xml")
1424+
@ActiveProfiles("dev")
1425+
public class TransferServiceTest {
1426+
1427+
@Autowired
1428+
private TransferService transferService;
1429+
1430+
@Test
1431+
public void testTransferService() {
1432+
// test the transferService
1433+
}
1434+
}</programlisting>
1435+
1436+
<para>When TransferServiceTest is run, its ApplicationContext will
1437+
be loaded from the app-config.xml configuration file in the root of
1438+
the classpath. If you inspect app-config.xml you'll notice that the
1439+
accountRepository bean has a dependency on a dataSource bean;
1440+
however, dataSource is not defined as a top-level bean. Instead,
1441+
dataSource is defined twice: once in the production profile and once
1442+
in the dev profile.</para>
1443+
1444+
<para>By annotating TransferServiceTest with @ActiveProfiles("dev")
1445+
we instruct the Spring TestContext Framework to load the
1446+
ApplicationContext with the active profiles set to {"dev"}. As a
1447+
result, an embedded database will be created, and the
1448+
accountRepository bean will be wired with a reference to the
1449+
development DataSource. And that's likely what we want in an
1450+
integration test.</para>
1451+
1452+
<para>The following code listings demonstrate how to implement the
1453+
same configuration and integration test but using @Configuration
1454+
classes instead of XML.</para>
1455+
1456+
<programlisting language="java">@Configuration
1457+
@Profile("dev")
1458+
public class StandaloneDataConfig {
1459+
1460+
@Bean
1461+
public DataSource dataSource() {
1462+
return new EmbeddedDatabaseBuilder()
1463+
.setType(EmbeddedDatabaseType.HSQL)
1464+
.addScript("classpath:com/bank/config/sql/schema.sql")
1465+
.addScript("classpath:com/bank/config/sql/test-data.sql")
1466+
.build();
1467+
}
1468+
}</programlisting>
1469+
1470+
<programlisting language="java">@Configuration
1471+
@Profile("production")
1472+
public class JndiDataConfig {
1473+
1474+
@Bean
1475+
public DataSource dataSource() throws Exception {
1476+
Context ctx = new InitialContext();
1477+
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
1478+
}
1479+
}</programlisting>
1480+
1481+
<programlisting language="java">@Configuration
1482+
@Profile("production")
1483+
public class JndiDataConfig {
1484+
1485+
@Bean
1486+
public DataSource dataSource() throws Exception {
1487+
Context ctx = new InitialContext();
1488+
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
1489+
}
1490+
}</programlisting>
1491+
1492+
<programlisting language="java">package com.bank.service;
1493+
1494+
@RunWith(SpringJUnit4ClassRunner.class)
1495+
@ContextConfiguration(
1496+
classes={
1497+
TransferServiceConfig.class,
1498+
StandaloneDataConfig.class,
1499+
JndiDataConfig.class})
1500+
@ActiveProfiles("dev")
1501+
public class TransferServiceTest {
1502+
1503+
@Autowired
1504+
private TransferService transferService;
1505+
1506+
@Test
1507+
public void testTransferService() {
1508+
// test the transferService
1509+
}
1510+
}</programlisting>
1511+
1512+
<para>In this variation, we have split the XML configuration into
1513+
three independent @Configuration classes:</para>
1514+
1515+
<itemizedlist>
1516+
<listitem>
1517+
<para>TransferServiceConfig: acquires a dataSource via
1518+
dependency injection using @Autowired</para>
1519+
</listitem>
1520+
1521+
<listitem>
1522+
<para>StandaloneDataConfig: defines a dataSource for an embedded
1523+
database suitable for developer tests</para>
1524+
</listitem>
1525+
1526+
<listitem>
1527+
<para>JndiDataConfig: defines a dataSource that is retrieved
1528+
from JNDI in a production environment</para>
1529+
</listitem>
1530+
</itemizedlist>
1531+
1532+
<para>As with the XML-based configuration example, we still annotate
1533+
TransferServiceTest with @ActiveProfiles("dev"), but this time we
1534+
specify all three configuration classes via the
1535+
@ContextConfiguration annotation. The body of the test class itself
1536+
remains completely unchanged.</para>
1537+
</section>
1538+
13601539
<section id="testcontext-ctx-management-caching">
13611540
<title>Context caching</title>
13621541

13631542
<para>By default, once an
13641543
<interfacename>ApplicationContext</interfacename> has been loaded
13651544
for a test it will be reused for <emphasis
13661545
role="bold">all</emphasis> subsequent tests that declare the same
1367-
unique context configuration within the same process — for example,
1368-
all tests run in a suite within an IDE or all tests run for the same
1369-
project with a build framework like Ant or Maven. Thus the setup
1370-
cost for loading an application context is incurred only once (per
1371-
test suite), and subsequent test execution is much faster.</para>
1546+
<emphasis>unique</emphasis> context configuration within the same
1547+
process — for example, all tests run in a suite within an IDE or all
1548+
tests run for the same project with a build framework like Ant or
1549+
Maven. Thus the setup cost for loading an application context is
1550+
incurred only once (per test suite), and subsequent test execution
1551+
is much faster.</para>
13721552

13731553
<para>In the unlikely case that a test corrupts the application
13741554
context and requires reloading — for example, by modifying a bean

0 commit comments

Comments
 (0)