How to send different values in cucumber features based on profile

First of all, I want to mention that this post continues the previous one where we have added AOP to execute some additional logic on cucumber steps. My recommendation will be to read mentioned post. Let’s start…

About Spring Profile

From official documentation a profile has the following role:
Spring Profiles provide a way to segregate parts of your application configuration and make it only available in certain environments. Any @Component or @Configuration can be marked with @Profile to limit when it is loaded:

@Configuration
@Profile("production")
public class ProductionConfiguration {

    // ...

}

In the normal Spring way, you can use a spring.profiles.active Environment property to specify which profiles are active. You can specify the property in any of the usual ways, for example, you could include it in your application.properties:

spring.profiles.active=dev,hsqldb

or specify on the command line using the switch --spring.profiles.active=dev,hsqldb.

Adding additional logic in JoinPoint Processor

Let’s start adding additional logic in JoinPoint to process string and to return a generated value. Under the code that calculates the execution time of the step, we will add the following snippet.

Stream methodArgs = Stream.of(joinPoint.getArgs());
        Object[] updatedArgs = methodArgs.map(this::getValueBaseOnPattern).toArray();
        log.info("Proper value from property is {}", updatedArgs);
        return joinPoint.proceed(updatedArgs);

Method getValueBaseOnPattern and his dependency we will create as private in our class.

    private Object getValueBaseOnPattern(Object objectArg) {
        Object result = objectArg;
        if (Objects.nonNull(objectArg)) {
            if (objectArg instanceof String) {
                String stringArg = (String) objectArg;
                if (stringArg.matches("^env\\(.*\\)")) {
                    result = getPropertyValue(StringUtils.substringBetween(stringArg, "\"", "\""));
                }
            }
        }
        return result;
    }

    private Object getPropertyValue(final String param) {
        if (Objects.nonNull(param)) {
            return environment.getProperty(param);
        } else throw new RuntimeException("Method parameter is null");
    }

Testing our results

To validate that we are getting proper property base on the spring profile we will create two properties files:

application-dev.yml

data:
  users:
    userName: DevUser

application-prod.yml

data:
  users:
    userName: ProdUser

Creating cucumber feature file:

Feature: Sending Property name from step and use value base on profile


@Run
  Scenario: Prints value that is send in step argument
    Given following property is printed env("data.users.userName")

With the following huge logic implementation:

    @Given("following property is printed {}")
    public void followingProperyIsPrinted(String property) {
        soutAction.print(property);
    }

And Depending on that spring profile we will set from the runner we expecting the corresponding value to be printed.

In moment then -Dspring.profiles.active=prod the printed value will be property from prod property file: ProdUser.

Full code example can be found under the following repo.