问题
I have a spring-boot
application for which I am writing IT tests.
The data for the tests comes from application-dev.properties
when I activate dev
profile
Here is what I have for tests:
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class ApplicationTests {
@Autowired
Environment env;
@Test
public void contextLoads() {
System.out.println(Arrays.toString((env.getActiveProfiles())));
}
}
ServiceITTest
public class ServiceITTest extends ApplicationTests {
@value
String username;
@value
String address;
@Autowired
MyService myService;
@Test
public void check_for_valid_username_address(){
myService.validate(username,address);
}
}
I want the above test to run only when I set the profile of "dev","qa". by default, it should not run.
Is it possible to get that fine control in spring boot testing?
回答1:
You would want to use the @IfProfileValue
annotation. Unfortunately it doesn't work directly on the active profiles but it can read a property so if you only define a specific property within the profiles that you want to run the test on then you can use that annotation on that specific property.
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html#integration-testing-annotations-junit
回答2:
It works also with active profiles - there is a property value containing active profiles:
Test only active with specific profile:
@IfProfileValue(name = "spring.profiles.active", values = {"specific"})
Since i have tests that should NOT run if specific profile is active i added this to those tests:
@ActiveProfiles(profiles = {"default"})
It does not work with @IfProfileValue
and "default" and i also didn't found any "run if specific profile is not active.
回答3:
In Spring you can also use the @DisabledIf
annotation. It allows for specifying a Spring Expression Language expression. See this blog post for examples.
JUnit 5 also has:
@DisabledIfEnvironmentVariable
@DisabledIfSystemProperty
回答4:
I wanted to exclude tests that required an external service but I couldn't get that to work the way I wanted (more or less a non-existent @IfNotProfileValue
).
As an alternative, I used the JUnit Assume.assumeThat which provided the behavior I wanted. e.g.,
Assume.assumeThat("Skipping Test: No username property", this.username, not(isEmptyString()));
I ended up not using a profile to drive it but you should be able to define a property or use the Environment to determine if a profile is active.
The assumeThat
can be used in @Test
and @Before
methods but be aware that the @After
methods will still run so cleanup might need a code guard.
回答5:
You can get the active profiles using org.springframework.core.env.Environment
:
(Beware, it's Kotlin.)
@Autowired
private val environment: Environment? = null
private fun isProfileActive(name: String) = environment!!.activeProfiles.contains(name)
@Test fun onlyOnOpenShift {
org.junit.Assume.assumeTrue(isProfileActive("openshift"));
...
}
If you have a lot of cases where you would use it (which I would suggest might hint that you're doing something wrongly), then it may pay off to decorate the test method with an annotation like @OnlyIfProfileActive("openshift")
and process it with your own JUnit extension, like, implementing org.junit.jupiter.api.extension.BeforeTestExecutionCallback
and determine if the method should run. In such case, the environment can be obtained from the Spring test runner.
@Test @OnlyIfProfileActive("openshift")
fun onlyOnOpenShift {
...
}
Which, I suspect, is what annotations like @IfProfileValue
do. But here you would have more control.
For instance, to make it versatile, it could be an expression evaluated with JEXL or JUEL or such.
@Test @SpringProfilesCondition("openshift && !mockDatabase")
fun onlyOnOpenShift {
...
}
来源:https://stackoverflow.com/questions/60352953/cannot-execute-junit-5-test-only-for-one-spring-profile