简体   繁体   中英

Java Spring Boot Test: How to exclude java configuration class from test context

I have a Java web app with spring boot

When run test I need to exclude some Java config files:

Test config (need to include when test run):

@TestConfiguration
@PropertySource("classpath:otp-test.properties")
public class TestOTPConfig { }

Production config (need to exclude when test run):

 @Configuration
 @PropertySource("classpath:otp.properties")
 public class OTPConfig { }

Test class (with explicit config class):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestAMCApplicationConfig.class)
public class AuthUserServiceTest { .... }

Test config:

@TestConfiguration
@Import({ TestDataSourceConfig.class, TestMailConfiguration.class, TestOTPConfig.class })
@TestPropertySource("classpath:amc-test.properties")
public class TestAMCApplicationConfig extends AMCApplicationConfig { }

Also have class:

@SpringBootApplication
public class AMCApplication { }

When test is running OTPConfig used, but I need TestOTPConfig ...

How can I do it?

Typically you would use Spring profiles to either include or exclude Spring beans, depending on which profile is active. In your situation you could define a production profile, which could be enabled by default; and a test profile. In your production config class you would specify the production profile:

@Configuration
@PropertySource("classpath:otp.properties")
@Profile({ "production" })
public class OTPConfig {
}

The test config class would specify the test profile:

@TestConfiguration
@Import({ TestDataSourceConfig.class, TestMailConfiguration.class,    TestOTPConfig.class })
@TestPropertySource("classpath:amc-test.properties")
@Profile({ "test" })
public class TestAMCApplicationConfig extends AMCApplicationConfig {
}

Then, in your test class you should be able to say which profiles are active:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestAMCApplicationConfig.class)
@ActiveProfiles({ "test" })
public class AuthUserServiceTest {
  ....
}

When you run your project in production you would include "production" as a default active profile, by setting an environment variable:

JAVA_OPTS="-Dspring.profiles.active=production"

Of course your production startup script might use something else besides JAVA_OPTS to set the Java environment variables, but somehow you should set spring.profiles.active .

You can also use @ConditionalOnProperty like below:

@ConditionalOnProperty(value="otpConfig", havingValue="production")
@Configuration
@PropertySource("classpath:otp.properties")
public class OTPConfig { }

and for tests:

@ConditionalOnProperty(value="otpConfig", havingValue="test")
@Configuration
@PropertySource("classpath:otp-test.properties")
public class TestOTPConfig { }

Then specify in your main/resources/config/application.yml

otpConfig: production

and in your test/resources/config/application.yml

otpConfig: test

You can also just mock the configuration you don't need. For example:

@MockBean
private AnyConfiguration conf;

Put it into your test class. This should help to avoid that the real AnyConfiguration is being loaded.

Additionally, for excluding auto configuration:

@EnableAutoConfiguration(exclude=CassandraDataAutoConfiguration.class)
public class // ...

The easiest way that I use -

  1. Put @ConditionalOnProperty in my main source code.
  2. Then define a test bean and add it as a part of the test configuration. Either import that configuration in the main test class or any other way. This is only needed when you need to register a test bean. If you do not need that bean then go to next step.
  3. Add a property in application.properties under src/test/resources to disable the use of configuration class that is present in the main folder.

Voila!

You can use @ConditionalOnMissingClass("org.springframework.test.context.junit4.SpringJUnit4ClassRunner") in Configuration class. SpringJUnit4ClassRunner can be replaced by any class which only exits in test environment.

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