Load different application.yml in SpringBoot Test

前端 未结 11 1108
天涯浪人
天涯浪人 2020-11-30 22:09

I\'m using a spring boot app which runs my src/main/resources/config/application.yml.

When I run my test case by :

@RunWith(SpringJUnit4ClassRunner.c         


        
相关标签:
11条回答
  • 2020-11-30 22:39

    One option is to work with profiles. Create a file called application-test.yml, move all properties you need for those tests to that file and then add the @ActiveProfiles annotation to your test class:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @WebAppConfiguration
    @IntegrationTest
    @ActiveProfiles("test") // Like this
    public class MyIntTest{
    }
    

    Be aware, it will additionally load the application-test.yml, so all properties that are in application.yml are still going to be applied as well. If you don't want that, either use a profile for those as well, or override them in your application-test.yml.

    0 讨论(0)
  • 2020-11-30 22:40

    If you need to have production application.yml completely replaced then put its test version to the same path but in test environment (usually it is src/test/resources/)

    But if you need to override or add some properties then you have few options.

    Option 1: put test application.yml in src/test/resources/config/ directory as @TheKojuEffect suggests in his answer.

    Option 2: use profile-specific properties: create say application-test.yml in your src/test/resources/ folder and:

    • add @ActiveProfiles annotation to your test classes:

      @SpringBootTest(classes = Application.class)
      @ActiveProfiles("test")
      public class MyIntTest {
      
    • or alternatively set spring.profiles.active property value in @SpringBootTest annotation:

      @SpringBootTest(
              properties = ["spring.profiles.active=test"],
              classes = Application.class,
      )
      public class MyIntTest {
      

    This works not only with @SpringBootTest but with @JsonTest, @JdbcTests, @DataJpaTest and other slice test annotations as well.

    And you can set as many profiles as you want (spring.profiles.active=dev,hsqldb) - see farther details in documentation on Profiles.

    0 讨论(0)
  • 2020-11-30 22:46

    You can set your test properties in src/test/resources/config/application.yml file. Spring Boot test cases will take properties from application.yml file in test directory.

    The config folder is predefined in Spring Boot.

    As per documentation:

    If you do not like application.properties as the configuration file name, you can switch to another file name by specifying a spring.config.name environment property. You can also refer to an explicit location by using the spring.config.location environment property (which is a comma-separated list of directory locations or file paths). The following example shows how to specify a different file name:

    java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
    

    The same works for application.yml

    Documentation:

    https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-application-property-files

    https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files

    0 讨论(0)
  • 2020-11-30 22:47

    This might be considered one of the options. now if you wanted to load a yml file ( which did not get loaded by default on applying the above annotations) the trick is to use

    @ContextConfiguration(classes= {...}, initializers={ConfigFileApplicationContextInitializer.class})
    

    Here is a sample code

    @RunWith(SpringRunner.class)
    @ActiveProfiles("test")
    @DirtiesContext
    @ContextConfiguration(classes= {DataSourceTestConfig.class}, initializers = {ConfigFileApplicationContextInitializer.class})
    public class CustomDateDeserializerTest {
    
    
        private ObjectMapper objMapper;
    
        @Before
        public void setUp() {
            objMapper = new ObjectMapper();
    
        }
    
        @Test
        public void test_dateDeserialization() {
    
        }
    }
    

    Again make sure that the setup config java file - here DataSourceTestConfig.java contains the following property values.

    @Configuration
    @ActiveProfiles("test")
    @TestPropertySource(properties = { "spring.config.location=classpath:application-test.yml" })
    public class DataSourceTestConfig implements EnvironmentAware {
    
        private Environment env;
    
        @Bean
        @Profile("test")
        public DataSource testDs() {
           HikariDataSource ds = new HikariDataSource();
    
            boolean isAutoCommitEnabled = env.getProperty("spring.datasource.hikari.auto-commit") != null ? Boolean.parseBoolean(env.getProperty("spring.datasource.hikari.auto-commit")):false;
            ds.setAutoCommit(isAutoCommitEnabled);
            // Connection test query is for legacy connections
            //ds.setConnectionInitSql(env.getProperty("spring.datasource.hikari.connection-test-query"));
            ds.setPoolName(env.getProperty("spring.datasource.hikari.pool-name"));
            ds.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
            long timeout = env.getProperty("spring.datasource.hikari.idleTimeout") != null ? Long.parseLong(env.getProperty("spring.datasource.hikari.idleTimeout")): 40000;
            ds.setIdleTimeout(timeout);
            long maxLifeTime = env.getProperty("spring.datasource.hikari.maxLifetime") != null ? Long.parseLong(env.getProperty("spring.datasource.hikari.maxLifetime")): 1800000 ;
            ds.setMaxLifetime(maxLifeTime);
            ds.setJdbcUrl(env.getProperty("spring.datasource.url"));
            ds.setPoolName(env.getProperty("spring.datasource.hikari.pool-name"));
            ds.setUsername(env.getProperty("spring.datasource.username"));
            ds.setPassword(env.getProperty("spring.datasource.password"));
            int poolSize = env.getProperty("spring.datasource.hikari.maximum-pool-size") != null ? Integer.parseInt(env.getProperty("spring.datasource.hikari.maximum-pool-size")): 10;
            ds.setMaximumPoolSize(poolSize);
    
            return ds;
        }
    
        @Bean
        @Profile("test")
        public JdbcTemplate testJdbctemplate() {
            return new JdbcTemplate(testDs());
        }
    
        @Bean
        @Profile("test")
        public NamedParameterJdbcTemplate testNamedTemplate() {
            return new NamedParameterJdbcTemplate(testDs());
        }
    
        @Override
        public void setEnvironment(Environment environment) {
            // TODO Auto-generated method stub
            this.env = environment;
        }
    }
    
    0 讨论(0)
  • 2020-11-30 22:51

    See this: Spring @PropertySource using YAML

    I think the 3rd answer has what you're looking for, i.e have a separate POJO to map your yaml values into:

    @ConfigurationProperties(path="classpath:/appprops.yml", name="db")
    public class DbProperties {
        private String url;
        private String username;
        private String password;
    ...
    }
    

    Then annotate your test class with this:

    @EnableConfigurationProperties(DbProperties.class)
    public class PropertiesUsingService {
    
        @Autowired private DbProperties dbProperties;
    
    }
    
    0 讨论(0)
  • 2020-11-30 22:52

    Spring-boot framework allows us to provide YAML files as a replacement for the .properties file and it is convenient.The keys in property files can be provided in YAML format in application.yml file in the resource folder and spring-boot will automatically take it up.Keep in mind that the yaml format has to keep the spaces correct for the value to be read correctly.

    You can use the @Value("${property}") to inject the values from the YAML files. Also Spring.active.profiles can be given to differentiate between different YAML for different environments for convenient deployment.

    For testing purposes, the test YAML file can be named like application-test.yml and placed in the resource folder of the test directory.

    If you are specifying the application-test.yml and provide the spring test profile in the .yml, then you can use the @ActiveProfiles('test') annotation to direct spring to take the configurations from the application-test.yml that you have specified.

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

    If you are using JUnit 5 then no need for other annotations as @SpringBootTest already include the springrunner annotation. Keeping a separate main ApplicationTest.class enables us to provide separate configuration classes for tests and we can prevent the default configuration beans from loading by excluding them from a component scan in the test main class. You can also provide the profile to be loaded there.

    @SpringBootApplication(exclude=SecurityAutoConfiguration.class)
    public class ApplicationTest {
     
        public static void main(String[] args) {
            SpringApplication.run(ApplicationTest.class, args);
        }
    }
    

    Here is the link for Spring documentation regarding the use of YAML instead of .properties file(s): https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

    0 讨论(0)
提交回复
热议问题