Ich habe eine Webanwendung, bei der ich das typische Problem habe, dass unterschiedliche Konfigurationsdateien für verschiedene Umgebungen erforderlich sind. Einige Konfigurationen werden als JNDI-Datenquellen auf dem Anwendungsserver abgelegt, einige Konfigurationen verbleiben jedoch in Eigenschaftsdateien.
Daher möchte ich die Funktion Federprofile verwenden.
Mein Problem ist, dass ich den Testfall nicht zum Laufen bekomme.
context.xml:
<context:property-placeholder
location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/>
Testfall:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
"classpath:context.xml" })
public class TestContext {
@Test
public void testContext(){
}
}
Das Problem scheint zu sein, dass die Variable zum Laden des Profils nicht aufgelöst wird:
Caused by: Java.io.FileNotFoundException: class path resource [META-INF/spring/config_${spring.profiles.active}.properties] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.Java:157)
at org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties(PropertiesLoaderSupport.Java:181)
at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.Java:161)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.Java:138)
... 31 more
Das aktuelle Profil sollte mit der Annotation @ActiveProfile
festgelegt werden. Da es sich um einen Testfall handelt, kann ich den web.xml
nicht verwenden. Wenn möglich, möchte ich auch Laufzeitoptionen vermeiden. Der Test sollte so laufen, wie es ist (wenn möglich).
Wie kann ich das Profil richtig aktivieren? Kann das Profil mit einer context.xml festgelegt werden? Kann ich die Variable in einer test-context.xml deklarieren, die den normalen Kontext aufruft?
Kann ich empfehlen, es so zu machen, definieren Sie Ihren Test so:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration
public class TestContext {
@Test
public void testContext(){
}
@Configuration
@PropertySource("classpath:/myprops.properties")
@ImportResource({"classpath:context.xml" })
public static class MyContextConfiguration{
}
}
mit dem folgenden Inhalt in der Datei myprops.properties:
spring.profiles.active=localtest
Damit sollte Ihre zweite Eigenschaftsdatei aufgelöst werden:
META-INF/spring/config_${spring.profiles.active}.properties
Als ich Bijus Antwort sah, fand ich eine funktionierende Lösung.
Ich habe eine zusätzliche Kontextdatei erstellt test-context.xml
:
<context:property-placeholder location="classpath:config/spring-test.properties"/>
Das Profil enthält:
spring.profiles.active=localtest
Und den Test mit laden:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
"classpath:config/test-context.xml" })
public class TestContext {
@Test
public void testContext(){
}
}
Dies erspart einige Arbeit beim Erstellen mehrerer Testfälle.
Die beste Methode ist, @ActiveProfiles Annotation zu entfernen und folgende Schritte auszuführen:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
TestPreperationExecutionListener.class
})
@Transactional
@ContextConfiguration(locations = {
"classpath:config/test-context.xml" })
public class TestContext {
@BeforeClass
public static void setSystemProperty() {
Properties properties = System.getProperties();
properties.setProperty("spring.profiles.active", "localtest");
}
@AfterClass
public static void setSystemProperty() {
System.clearProperty("spring.profiles.active");
}
@Test
public void testContext(){
}
}
Und Ihre test-context.xml sollte folgendes haben:
<context:property-placeholder
location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/>
public class LoginTest extends BaseTest {
@Test
public void exampleTest( ){
// Test
}
}
Vererbt sich aus einer Basistestklasse (dieses Beispiel ist testng
und nicht jUnit
, aber die ActiveProfiles
ist gleich):
@ContextConfiguration(locations = { "classpath:spring-test-config.xml" })
@ActiveProfiles(resolver = MyActiveProfileResolver.class)
public class BaseTest extends AbstractTestNGSpringContextTests { }
MyActiveProfileResolver
kann jede Logik enthalten, die zur Bestimmung des zu verwendenden Profils erforderlich ist:
public class MyActiveProfileResolver implements ActiveProfilesResolver {
@Override
public String[] resolve(Class<?> aClass) {
// This can contain any custom logic to determine which profiles to use
return new String[] { "exampleProfile" };
}
}
Dadurch wird das Profil festgelegt, das dann zum Auflösen der vom Test erforderlichen Abhängigkeiten verwendet wird.