简体   繁体   中英

Dynamically change value from a property file in Spring Boot Cucumber test

I have a Spring Boot application in which a specific bean (MyClass) gets a @Value annotated property whose value is defined in application.properties file:

@Component
public class MyClass {
    
  private String type;

  public MyClass(@Value("${type}") String type) { 
    this.type=type;
  }

  public String doSomething () {...} 
}

application.properties file includes the following: type=typeA

The testing is done using Cucumber, and I would like to test the behavior of the method MyClass.doSomthing when the value of type is not typeA but typeB , so I thought about doing the following:

The scenario in the *.feature file will start like this:

Scenario: Validating doSomething when type is B
    Given The value of type is typeB
    Then Validate doSomething 

in the *StepDef file - the implementation of the Given step should somehow change the value of type to typeB , so that the flow of MyClass.doSomthing will process typeB :

@Given("The value of type is typeB")
public void changeTypeToB() {
    ...
}

My question is: How do I set the value of type to typeB (in the method changeTypeToB ) considering the fact the during the test the Spring profile is the default one, hence the initial value of type is typeA ?

Thanks!

Dino

You are effectively trying to change a configuration value after the Spring application has already started.

This generally requires starting a new application context and in Cucumber terms this means starting a separate test suite.

You would organize this like so:

package com.example.stepdefinitions;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(
  extraGlue = "com.example.app.config.typea"
)
public class RunCucumberTestTypeA {

}

And:

package com.example.stepdefinitions;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(
  extraGlue = "com.example.app.config.typeb"
)
public class RunCucumberTestTypeB {

}

Then use the context configuration to override the properties:

package com.example.app.config.typeb;

@CucumberContextConfiguration
@SpringBootTest(properties = {
        "com.example.value=Hello", 
        "com.example.value2=World"
})
public class CucumberTestContextConfiguration {

}

Or enable a profile and put your properties in application-type-b.yml :

package com.example.app.config.typeb;

@CucumberContextConfiguration
@SpringBootTest
@ActiveProfiles("type-b")
public class CucumberTestContextConfiguration {

}

As a sanity check you can then verify if the right configuration is used in the The value of type is typeB step.

This is quite a bit of setup though. You can also create a new instance of MyClass that isn't managed by the spring application context and run your tests on that.

@Given("The value of type is typeB")
public void changeTypeToB() {
    testInstance = new MyClass("typeB")
}
@Then("validate doSomething")
public void changeTypeToB() {
    testInstance.doSomething()
    // validate test instance did something
}

Finally you may want to reconsider your design. It sounds like typeB could be a feature toggle (because you want to change it at runtime) in which case using @Value wouldn't be the right approach.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM