I have a config class AppConfig
to receive environment variables and use them inside service MyService
// application.yml
app-config:
env-var1: ${ENV_VAR1:}
env-var2: ${ENV_VAR2:}
env-var3: ${ENV_VAR3:}
env-var4: ${ENV_VAR4:}
env-var5: ${ENV_VAR5:}
// AppConfig.java
@Data
@EnableConfigurationProperties
@ConfigurationProperties(value = "app-config")
public class AppConfig {
private String envVar1;
private String envVar2;
private String envVar3;
private String envVar4;
private String envVar5;
}
// MyService.java
@Slf4j
@Service
public class MyService {
@Autowired
AppConfig appConfig;
public void doSomething() {
log.info(appConfig.getEnvVar1());
log.info(appConfig.getEnvVar2());
// business logic controlled by appConfig.envVar1 and appConfig.envVar2
// other variables not used
}
}
Now I am writing unit test for MyService
// MyServiceTest.java
@SpringBootTest
class MyServiceTest {
@Autowired
AppConfig appConfig;
@Autowired
MyService myService;
@BeforeEach
void setUp() {
// reset override
}
@AfterEach
void tearDown() {
// reset override
}
@Test
void doSomething_envVar1() {
// override appConfig.envVar1 only
myService.doSomething()
}
@Test
void doSomething_envVar2() {
// override appConfig.envVar2 only
myService.doSomething()
}
}
How can I override only one variable inside AppConfig
in one test only (and reset it after the test)?
CodePudding user response:
I think you can use @DirtiesContext annotation. Using this annotation, you can restart spring context when every test methods end.
@SpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class MyServiceTest {
@Autowired
AppConfig appConfig;
@Autowired
MyService myService;
@Test
void doSomething_envVar1() {
// override appConfig.envVar1 only
myService.doSomething()
}
@Test
void doSomething_envVar2() {
// appConfig.envVar1 is not effected by envVar1() test
// override appConfig.envVar2 only
myService.doSomething()
}
}
more examples are on baeldung guide: https://www.baeldung.com/spring-dirtiescontext
CodePudding user response:
You can override yaml variables for the test. You need a test profile application-test.yaml
. There you can override your variables. Also annotate your test class with @ActiveProfiles("test")
. Your test will use default yaml and override variables, that are declared in "test" yaml. But you'll have to isolate the test, that uses different yaml params into another test. Check out this question: Load different application.yml in SpringBoot Test
@ActiveProfiles("test")
@SpringBootTest
class SpecialMyServiceTest {
Also you can specify properties in @SpringBootTest annotation
@SpringBootTest(
properties = { "spring.application.name=example", "ENV_VARIABLE=secret" }
)
But still, they spread on all test cases of this class
There's also a @DynamicPropertySource annotation, maybe it will help you. Check out this page - maybe you'll find suitable solution there