Reputation: 209
I am trying to use different properties with cucumber to run integration tests for my spring boot app. I can get it to run if I use the default properties loaded in the main Application class. However when I specify @TestPropertySource to this different location of config properties, it still uses the main Application class's application context. So its the application Context at test execution is the same as it would be when the app would be running on a server. I do not want this.
This is a work related web app using the Spring Boot 1.5.18, Cucumber 4.2.2.
The directory structure is src/main/java for all my java classes and packages, src/main/resources with the application.properties and some others, a root level folder with environment logging and security properties. Then I have src/test/java with my cucumber code and src/test/resources with my modified application.properties file i'd like to use at test execution. I'd also like to specify a different environment, security, logging config property files for testing as well.
This is my ApplicationTest.Java class where I am trying to use the different property sources.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource( value =
{"file:${env.dir}/deploy/acceptance/config/env.properties",
"file:${env.dir}/deploy/acceptance/config/AppConfig.properties",
"file:${env.dir}/deploy/acceptance/security/auth.properties",
"classpath:application-test.properties"})
public abstract class ApplicationTest {
public ApplicationTest() {
}
This is my Cucumber4Test.Java class
@RunWith(Cucumber.class)
@CucumberOptions(features = "src/test/resources",
plugin = {"pretty", "html:target/cucumber",
"junit:target/reports/cucumber.json"}, glue = { "com.test.packages.cucumber"
}, monochrome = true)
public class CucumberTest {
}
I am not sure if I am missing anything in those classes as I followed a tutorial. But as I said, if I do not set any property sources in my ApplicationTest class, and run the CucumberTest.java as a junit in eclipse, or run mvn clean install, mvn test etc, the cucumber tests will execute as expected.
I've scoured the questions here trying a bunch of things and nothing seems to work for me. Override @PropertySource with @TestPropertySource in Spring Boot
Load different application.yml in SpringBoot Test
EDIT: The reason I believe @TestPropertySource isn't working is due to the following: property source precedence in Spring. When I load up cucumber in src/test/java, it loads those properties I've specified, but then it starts the app in the src/main/java folder. Here its loading the default properties in Application.java. Spring documentation says whichever properties are loaded last take precedence so my TestPropertySource is getting overwritten when the app starts.
My working solution: I wanted to get cucumber to run in Jenkins in a separate job from our build and deploy pipeline. But couldn't find a way around my work's standard for path and directory structure for configs and properties. So what I did:
1) Add properties i needed into the classpath in src/test/resources.
2) Now this is a bit hacky, but a second Application.java in src/test/java with the @Propertysources reflecting the properties I wanted to use.
3) In jenkins I execute a pre-build step before I run a mvn test. This shell just moves the src/test/java/package/with/Application.java into src/main/java/package/with/Application.java. This overwrites the usual Application.java class with the different properties.
4) run mvn test
5) profit
Upvotes: 2
Views: 15037
Reputation: 12069
This works.
Using the default application.
package cucumber.examples.spring.txn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@SpringBootApplication
@EnableWebMvc
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And some application.properties
key=App
Then running with:
package cucumber.examples.spring.txn;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
@RunWith(Cucumber.class)
public class RunCukesTest {
}
and using this test context configuration
package cucumber.examples.spring.txn;
import cucumber.api.java.Before;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
@SpringBootTest
@AutoConfigureMockMvc
public class CucumberContextConfiguration {
@Value("${key}")
private String value;
@Before
public void setup_cucumber_spring_context(){
// Dummy method so cucumber will recognize this class as glue
// and use its context configuration.
System.out.println("Property was " + value);
}
}
Will print Property was App
.
Adding @TestPropertySource("classpath:test.properties")
to the CucumberContextConfiguration
and creating a test.properties
file containing
key=Test
Will print Property was Test
.
Upvotes: 1