<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=sbrannen" rel="nofollow">Sam Brannen</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-7960?redirect=false" rel="nofollow">SPR-7960</a></strong> and commented</p>
<h4 dir="auto">Overview</h4>
<p dir="auto">Spring 3.1 introduces support for <em>bean definition profiles</em>, such as 'production', 'dev', etc.</p>
<p dir="auto">The Spring TestContext framework should be extended to support declarative configuration of bean definition profiles on a per-ApplicationContext basis.</p>
<p dir="auto">One option would be to provide an attribute in the <code class="notranslate">@ContextConfiguration</code> annotation to allow the <code class="notranslate">spring.profiles.active</code> value to be set declaratively.</p>
<h4 dir="auto">Further Resources</h4>
<ul dir="auto">
<li><a href="http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/#comment-184808" rel="nofollow">Comment on SpringSource blog</a></li>
</ul>
<h4 dir="auto">Example Tests Using <code class="notranslate">@ActiveProfiles</code></h4>
<p dir="auto">The following examples -- which are taken from the Spring test suite -- show how to declare which active profiles to use when loading an application context via the new <code class="notranslate">@ActiveProfiles</code> annotation.</p>
<hr>
<h5 dir="auto">Testing Active Profiles with <code class="notranslate">@Configuration</code> Classes</h5>
<p dir="auto">\</p>
<ul dir="auto">
<li><code class="notranslate">DefaultProfileConfig</code>: <code class="notranslate">@Configuration</code> class without a <code class="notranslate">@Profile</code> declaration</li>
<li><code class="notranslate">DevProfileConfig</code>: <code class="notranslate">@Configuration</code> class with a <code class="notranslate">@Profile("dev")</code> declaration</li>
<li><code class="notranslate">DefaultProfileAnnotationConfigTests</code>: JUnit 4 test that instructs the TestContext framework to load an application context from both the <code class="notranslate">DefaultProfileConfig</code> and <code class="notranslate">DevProfileConfig</code> <code class="notranslate">@Configuration</code> classes</li>
<li><code class="notranslate">DevProfileAnnotationConfigTests</code>: extends <code class="notranslate">DefaultProfileAnnotationConfigTests</code> and instructs the TestContext framework to activate the "<em>dev</em>" profile via <code class="notranslate">@ActiveProfiles("dev")</code></li>
</ul>
<p dir="auto">Note that the autowired <code class="notranslate">employee</code> is <code class="notranslate">null</code> in <code class="notranslate">DefaultProfileAnnotationConfigTests</code> but <strong>not</strong> <code class="notranslate">null</code> in <code class="notranslate">DevProfileAnnotationConfigTests</code>; whereas, the <code class="notranslate">pet</code> is non-null for both the <em>default</em> and <em>dev</em> profile.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@Configuration
public class DefaultProfileConfig {

	@Bean
	public Pet pet() {
		return new Pet(&quot;Fido&quot;);
	}
}"><pre class="notranslate"><code class="notranslate">@Configuration
public class DefaultProfileConfig {

	@Bean
	public Pet pet() {
		return new Pet("Fido");
	}
}
</code></pre></div>
<p dir="auto">\</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@Profile(&quot;dev&quot;)
@Configuration
public class DevProfileConfig {

	@Bean
	public Employee employee() {
		Employee employee = new Employee();
		employee.setName(&quot;John Smith&quot;);
		employee.setAge(42);
		employee.setCompany(&quot;Acme Widgets, Inc.&quot;);
		return employee;
	}
}"><pre class="notranslate"><code class="notranslate">@Profile("dev")
@Configuration
public class DevProfileConfig {

	@Bean
	public Employee employee() {
		Employee employee = new Employee();
		employee.setName("John Smith");
		employee.setAge(42);
		employee.setCompany("Acme Widgets, Inc.");
		return employee;
	}
}
</code></pre></div>
<p dir="auto">\</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { DefaultProfileConfig.class, DevProfileConfig.class },
  loader = AnnotationConfigContextLoader.class)
public class DefaultProfileAnnotationConfigTests {

	@Autowired
	protected Pet pet;

	@Autowired(required = false)
	protected Employee employee;

	@Test
	public void pet() {
		assertNotNull(pet);
		assertEquals(&quot;Fido&quot;, pet.getName());
	}

	@Test
	public void employee() {
		assertNull(&quot;employee bean should not be created for the default profile&quot;, employee);
	}
}"><pre class="notranslate"><code class="notranslate">@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { DefaultProfileConfig.class, DevProfileConfig.class },
  loader = AnnotationConfigContextLoader.class)
public class DefaultProfileAnnotationConfigTests {

	@Autowired
	protected Pet pet;

	@Autowired(required = false)
	protected Employee employee;

	@Test
	public void pet() {
		assertNotNull(pet);
		assertEquals("Fido", pet.getName());
	}

	@Test
	public void employee() {
		assertNull("employee bean should not be created for the default profile", employee);
	}
}
</code></pre></div>
<p dir="auto">\</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@ActiveProfiles(&quot;dev&quot;)
public class DevProfileAnnotationConfigTests extends DefaultProfileAnnotationConfigTests {

	@Test
	@Override
	public void employee() {
		assertNotNull(&quot;employee bean should be loaded for the 'dev' profile&quot;, employee);
		assertEquals(&quot;John Smith&quot;, employee.getName());
	}

}"><pre class="notranslate"><code class="notranslate">@ActiveProfiles("dev")
public class DevProfileAnnotationConfigTests extends DefaultProfileAnnotationConfigTests {

	@Test
	@Override
	public void employee() {
		assertNotNull("employee bean should be loaded for the 'dev' profile", employee);
		assertEquals("John Smith", employee.getName());
	}

}
</code></pre></div>
<hr>
<h5 dir="auto">Testing Active Profiles with XML Configuration</h5>
<p dir="auto">\<br>
The <code class="notranslate">DefaultProfileXmlConfigTests</code> and <code class="notranslate">DevProfileXmlConfigTests</code> classes are analogous to the <code class="notranslate">DefaultProfileAnnotationConfigTests</code> and <code class="notranslate">DevProfileAnnotationConfigTests</code> classes described above. The difference is that both of these test classes use the XML-based configuration found in <code class="notranslate">DefaultProfileXmlConfigTests-context.xml</code>, which combines the declaration of the <em>default</em> and <em>dev</em> profiles in a single XML file. Otherwise, the use of <code class="notranslate">@ActiveProfiles</code> and the behavior of the tests is identical.</p>
<div class="highlight highlight-text-xml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd&quot;&gt;

    &lt;bean id=&quot;pet&quot; class=&quot;org.springframework.beans.Pet&quot;&gt;
        &lt;constructor-arg value=&quot;Fido&quot; /&gt;
    &lt;/bean&gt;

    &lt;beans profile=&quot;dev&quot;&gt;
        &lt;bean id=&quot;employee&quot; class=&quot;org.springframework.beans.Employee&quot;&gt;
            &lt;property name=&quot;name&quot; value=&quot;John Smith&quot; /&gt;
            &lt;property name=&quot;age&quot; value=&quot;42&quot; /&gt;
            &lt;property name=&quot;company&quot; value=&quot;Acme Widgets, Inc.&quot; /&gt;
        &lt;/bean&gt;
    &lt;/beans&gt;

&lt;/beans&gt;"><pre class="notranslate">&lt;?<span class="pl-ent">xml</span><span class="pl-e"> version</span>=<span class="pl-s"><span class="pl-pds">"</span>1.0<span class="pl-pds">"</span></span><span class="pl-e"> encoding</span>=<span class="pl-s"><span class="pl-pds">"</span>UTF-8<span class="pl-pds">"</span></span>?&gt;
&lt;<span class="pl-ent">beans</span> <span class="pl-e">xmlns</span>=<span class="pl-s"><span class="pl-pds">"</span>http://www.springframework.org/schema/beans<span class="pl-pds">"</span></span>
    <span class="pl-e">xmlns</span><span class="pl-e">:</span><span class="pl-e">xsi</span>=<span class="pl-s"><span class="pl-pds">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="pl-pds">"</span></span>
    <span class="pl-e">xsi</span><span class="pl-e">:</span><span class="pl-e">schemaLocation</span>=<span class="pl-s"><span class="pl-pds">"</span></span>
<span class="pl-s">        http://www.springframework.org/schema/beans</span>
<span class="pl-s">        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd<span class="pl-pds">"</span></span>&gt;

    &lt;<span class="pl-ent">bean</span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>pet<span class="pl-pds">"</span></span> <span class="pl-e">class</span>=<span class="pl-s"><span class="pl-pds">"</span>org.springframework.beans.Pet<span class="pl-pds">"</span></span>&gt;
        &lt;<span class="pl-ent">constructor-arg</span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>Fido<span class="pl-pds">"</span></span> /&gt;
    &lt;/<span class="pl-ent">bean</span>&gt;

    &lt;<span class="pl-ent">beans</span> <span class="pl-e">profile</span>=<span class="pl-s"><span class="pl-pds">"</span>dev<span class="pl-pds">"</span></span>&gt;
        &lt;<span class="pl-ent">bean</span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>employee<span class="pl-pds">"</span></span> <span class="pl-e">class</span>=<span class="pl-s"><span class="pl-pds">"</span>org.springframework.beans.Employee<span class="pl-pds">"</span></span>&gt;
            &lt;<span class="pl-ent">property</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>John Smith<span class="pl-pds">"</span></span> /&gt;
            &lt;<span class="pl-ent">property</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>age<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>42<span class="pl-pds">"</span></span> /&gt;
            &lt;<span class="pl-ent">property</span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>company<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>Acme Widgets, Inc.<span class="pl-pds">"</span></span> /&gt;
        &lt;/<span class="pl-ent">bean</span>&gt;
    &lt;/<span class="pl-ent">beans</span>&gt;

&lt;/<span class="pl-ent">beans</span>&gt;</pre></div>
<p dir="auto">\</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DefaultProfileXmlConfigTests {

	@Autowired
	protected Pet pet;

	@Autowired(required = false)
	protected Employee employee;


	@Test
	public void pet() {
		assertNotNull(pet);
		assertEquals(&quot;Fido&quot;, pet.getName());
	}

	@Test
	public void employee() {
		assertNull(&quot;employee bean should not be created for the default profile&quot;, employee);
	}
}"><pre class="notranslate"><code class="notranslate">@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class DefaultProfileXmlConfigTests {

	@Autowired
	protected Pet pet;

	@Autowired(required = false)
	protected Employee employee;


	@Test
	public void pet() {
		assertNotNull(pet);
		assertEquals("Fido", pet.getName());
	}

	@Test
	public void employee() {
		assertNull("employee bean should not be created for the default profile", employee);
	}
}
</code></pre></div>
<p dir="auto">\</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@ActiveProfiles(&quot;dev&quot;)
public class DevProfileXmlConfigTests extends DefaultProfileXmlConfigTests {

	@Test
	@Override
	public void employee() {
		assertNotNull(&quot;employee bean should be loaded for the 'dev' profile&quot;, employee);
		assertEquals(&quot;John Smith&quot;, employee.getName());
	}

}"><pre class="notranslate"><code class="notranslate">@ActiveProfiles("dev")
public class DevProfileXmlConfigTests extends DefaultProfileXmlConfigTests {

	@Test
	@Override
	public void employee() {
		assertNotNull("employee bean should be loaded for the 'dev' profile", employee);
		assertEquals("John Smith", employee.getName());
	}

}
</code></pre></div>
<hr>
<p dir="auto"><strong>Affects:</strong> 3.1 M1</p>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398112598" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/13033" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/13033/hovercard" href="https://github.com/spring-projects/spring-framework/issues/13033">#13033</a> Introduce SmartContextLoader SPI (<em><strong>"depends on"</strong></em>)</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398108841" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/12410" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/12410/hovercard" href="https://github.com/spring-projects/spring-framework/issues/12410">#12410</a> Decide what to do with <code class="notranslate">@IfProfileValue</code></li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398097973" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/10852" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/10852/hovercard" href="https://github.com/spring-projects/spring-framework/issues/10852">#10852</a> Provide TestContext support for <code class="notranslate">@Configuration</code> classes</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398088743" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/9538" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/9538/hovercard" href="https://github.com/spring-projects/spring-framework/issues/9538">#9538</a> Introduce strategy for determining if a profile value is enabled for a particular test environment</li>
</ul>
<p dir="auto">5 votes, 6 watchers</p>
<p dir="auto"><strong><a href="https://jira.spring.io/secure/ViewProfile.jspa?name=david_syer" rel="nofollow">Dave Syer</a></strong> opened <strong><a href="https://jira.spring.io/browse/SPR-7754?redirect=false" rel="nofollow">SPR-7754</a></strong> and commented</p>
<p dir="auto">Now that <code class="notranslate">@Profile</code> (and "profile" generally) has a meaning in the framework, the old test support for detecting system properties looks like it has an awkward name.  In Spring 3.1 terms, what <code class="notranslate">@IfProfileValue</code> does is detect key-value pairs in the Environment (not profiles).</p>
<p dir="auto">One simple thing we should definitely do is add a ProfileValueSource that can pull values from the Environment.</p>
<p dir="auto">More radically, maybe we could rename <code class="notranslate">@IfProfileValue</code>(name=,value=) to <code class="notranslate">@Environment</code>(key=,value=).</p>
<p dir="auto">Another suggestion is that we could provide a way to activate profiles declaratively for tests or test classes.  Something I've been playing with is this (new components ProfileSuite and <code class="notranslate">@ActiveProfile</code>):</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@RunWith(Suite.class)
@SuiteClasses({ HsqlTest.class, DerbyTest.class })
public class JdbcDaoIntegrationTests {

	@RunWith(ProfileSuite.class)
	@SuiteClasses({ JdbcSearchableJobInstanceDaoTests.class, JdbcSearchableJobExecutionDaoTests.class,
			JdbcSearchableStepExecutionDaoTests.class })
	public static abstract class BaseTest {
	}

	@ActiveProfile(&quot;hsql&quot;)
	public static class HsqlTest extends BaseTest {
	}

	@ActiveProfile(&quot;derby&quot;)
	public static class DerbyTest extends BaseTest {
	}

}"><pre class="notranslate"><span class="pl-c1">@</span><span class="pl-c1">RunWith</span>(<span class="pl-smi">Suite</span>.<span class="pl-k">class</span>)
<span class="pl-c1">@</span><span class="pl-c1">SuiteClasses</span>({ <span class="pl-smi">HsqlTest</span>.<span class="pl-k">class</span>, <span class="pl-smi">DerbyTest</span>.<span class="pl-k">class</span> })
<span class="pl-k">public</span> <span class="pl-k">class</span> <span class="pl-smi">JdbcDaoIntegrationTests</span> {

	<span class="pl-c1">@</span><span class="pl-c1">RunWith</span>(<span class="pl-smi">ProfileSuite</span>.<span class="pl-k">class</span>)
	<span class="pl-c1">@</span><span class="pl-c1">SuiteClasses</span>({ <span class="pl-smi">JdbcSearchableJobInstanceDaoTests</span>.<span class="pl-k">class</span>, <span class="pl-smi">JdbcSearchableJobExecutionDaoTests</span>.<span class="pl-k">class</span>,
			<span class="pl-smi">JdbcSearchableStepExecutionDaoTests</span>.<span class="pl-k">class</span> })
	<span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">abstract</span> <span class="pl-k">class</span> <span class="pl-smi">BaseTest</span> {
	}

	<span class="pl-c1">@</span><span class="pl-c1">ActiveProfile</span>(<span class="pl-s">"hsql"</span>)
	<span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">class</span> <span class="pl-smi">HsqlTest</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseTest</span> {
	}

	<span class="pl-c1">@</span><span class="pl-c1">ActiveProfile</span>(<span class="pl-s">"derby"</span>)
	<span class="pl-k">public</span> <span class="pl-k">static</span> <span class="pl-k">class</span> <span class="pl-smi">DerbyTest</span> <span class="pl-k">extends</span> <span class="pl-smi">BaseTest</span> {
	}

}</pre></div>
<p dir="auto">It says: run these three test classes twice each, once with profile "hsql" and once with profile "derby".  This has the nice feature that <code class="notranslate">@EnvironmentValue</code> can still be honoured inside the individual tests (per method).</p>
<hr>
<p dir="auto"><strong>Issue Links:</strong></p>
<ul dir="auto">
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398116421" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/13625" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/13625/hovercard" href="https://github.com/spring-projects/spring-framework/issues/13625">#13625</a> SystemProfileValueSource is not very compatible with the new 3.1 default system property profiles</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398110141" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/12615" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/12615/hovercard" href="https://github.com/spring-projects/spring-framework/issues/12615">#12615</a> TestContext framework should support declarative configuration of bean definition profiles</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398116387" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/13622" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/13622/hovercard" href="https://github.com/spring-projects/spring-framework/issues/13622">#13622</a> Allow overriding <code class="notranslate">@ActiveProfiles</code> in test classes with system property</li>
<li><a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="398167496" data-permission-text="Title is private" data-url="https://github.com/spring-projects/spring-framework/issues/16300" data-hovercard-type="issue" data-hovercard-url="/spring-projects/spring-framework/issues/16300/hovercard" href="https://github.com/spring-projects/spring-framework/issues/16300">#16300</a> Introduce annotation to skip test based on active Spring profile</li>
</ul>
<p dir="auto">6 votes, 7 watchers</p>