2

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

chamburger
  • 209
  • 1
  • 3
  • 11
  • I don't see a step definition in your `ApplicationTest` class. Withouth a step or hook defintion cucumber will ignore it. You may have to add a dummy step. – M.P. Korstanje Feb 01 '19 at 21:28
  • @mpkorstanje thanks. I actually have a common steps def class that is inherited from application test. This, I don’t think thoogh, is why the test protestors aren’t being honored when the application starts in Application.java – chamburger Feb 02 '19 at 22:44
  • I think your problem lies elsewhere. You should try to create a minimal example. You could use this as a basis: https://github.com/cucumber/cucumber-jvm/tree/master/examples/spring-txn Doing this it works for me. I'll post the details below. – M.P. Korstanje Feb 02 '19 at 23:07

1 Answers1

1

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.

M.P. Korstanje
  • 10,426
  • 3
  • 36
  • 58
  • Thanks but due to standards at work, I cannot change the properties sources in Application.java. When we deploy to servers, and need new instances created by the middleware team they have the directory structure and locations pre-determined this way so it makes deploys easier. That is my issue, and my solution is my workaround for that. Changing the standard would require a lot more work and multiple teams to change the way they do things. I really appreciate your help. – chamburger Feb 04 '19 at 16:35