2

We have multiple test classes in our spring boot application. Some of the classes contain integration tests, some contain unit tests. These means that if I (e.g. with maven) let all tests to be executed, it will run all tests in all classes.

What I like to achieve is that the integration tests are executed only, if a specific spring profile is set, e.g. via application.yml. I like e.g. to annotate the whole test class to define that the tests in this class are only executed if the specified spring profile is set. If it is not set, these tests shall be ignored.

  • The topic How can I use @IfProfileValue to test if a Profile is active? goes in exactly this direction. @IfProfileValue looks at first glance exactly like it is what I need. But as it is pointed out, it is not. I could use it, if I would set a specific system property. But I need to use a real spring profile (and not the system property spring.profiles.active - this would ignore a profile set via application.yml)
  • @Profile seems to look also to be what I need but as the topic Use @Profile to decide to execute test class shows, we should not use it.

So what can be done to achieve this? Note that there are a lot of questions about tests and spring profiles on stack overflow. But most of them point out how to set configurations in tests specific to spring profiles. That is not would I am looking for. I would like to execute or ignore the tests.

badera
  • 1,495
  • 2
  • 24
  • 49
  • Use surefire for unit test and Failsafe for your integration tests. Unit test ends with *Test.java and Integration test ends with *IT.java/*ITCase.java then you can set profiles to execute this. – Arundev Mar 08 '21 at 13:30

3 Answers3

2

I don't know exactly how you want to achieve it, but here is a way if you are using junit to conditionally ignore some tests at runtime simply using a configuration property:

application.properties:

test.enabled=true

then in your test code you can use org.junit.Assume and a property like the following:

@Value("${test.enabled}")
private Boolean testEnabled;

@Test
public void test {
    org.junit.Assume.assumeTrue(testEnabled);
    // your test code
}

now if you set the property test.enabled to true the test will run, otherwise it will be ignored.

Source: Conditionally ignoring tests in JUnit 4

Mohamed Ibrahim Elsayed
  • 2,734
  • 3
  • 23
  • 43
  • I assume this would still boot up whole spring application context, which ime is what generally eats most of the time, and not the test itself – Coderino Javarino Sep 15 '21 at 08:02
2

Using JUnit 5, you can use an @Autowired Environment to check if a profile is active @BeforeEach test is run: Assumptions.assumeTrue(Arrays.asList(this.environment.getActiveProfiles()).contains("integration"));

This checks for a profile named "integration" and works regardless of how the profile was set (system property, environment variable, application.yml, etc.).

If the profile is not active, the test will be ignored, which is similar to using the @Disabled annotation.

1

It is very easy. My solution in kotlin:

  1. Create annotation
import org.springframework.test.context.junit.jupiter.EnabledIf
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.annotation.AnnotationTarget.CLASS
import kotlin.annotation.AnnotationTarget.FUNCTION

@Target(CLASS, FUNCTION)
@Retention(RUNTIME)
@EnabledIf(
    expression = "#{environment.acceptsProfiles('integration')}",
    reason = "‍ Because spring.profiles.active = integration",
    loadContext = true)
annotation class Integration
  1. Use it:
import by.package.Integration


@Integration
internal class IntegrationTest {

    @Test
    // @Integration 
    fun test() {
       assertEquals(4, 2 + 2)
    }

@DisableIf annotation has opposite logic

Dmitry Kaltovich
  • 2,046
  • 19
  • 21
  • Nice. Is there a way to use an existing annotation? Say, exclude tests if they have @SpringBootTest annotation. – mayid Mar 09 '22 at 14:37