JeyJ
JeyJ

Reputation: 4070

Testing @ConfigurationProperties annotation without loading Spring context

I'm trying to test a class that has the @ConfigurationProperties annotation but without loading the entire Spring context. I tried using only the JUnit5's features in order to do that but until now didn't succeed in that.

I'm using spring-boot-starter-parent v2.6.2 .

The class I'm testing :

@ConfigurationProperties("db.mongo")
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class MongoProperties {
    private String host;
    private String db;
    private String user;
    private String password;
}

The application.yaml :

db:
  mongo:
    host: localhost
    db: test
    user: test-user
    password: secret

My Test class :

@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties({MongoProperties.class})
public class MongoPropertiesTest {

    @Autowired
    private  MongoProperties properties;

    @Test
    public void mongoPropertiesLoadedTest(){
        assertNotNull(properties.getDb());
        assertNotNull(properties.getHost());
        assertNotNull(properties.getPassword());
        assertNotNull(properties.getUser());
    }
}

The MongoProperties bean is injected successfully, but all the values inside are null and the asserts fail.

Adding the @SpringBootTest solves the issue of the null values in the instance of the bean, but it also starts the whole spring context which is what I don't want.

Upvotes: 10

Views: 7189

Answers (1)

Ken Chan
Ken Chan

Reputation: 90457

But using @ExtendWith(SpringExtension.class) will also start the spring context. The difference is that it starts the context in a traditional way but @SpringBootTest starts it in a spring-boot way. So no matter you use which of them , it still requires to start the spring context.

If your concern is to minimise the number of beans required to be loaded into the spring context when using @SpringBootTest, you can actually configure a specified @Configuration like the following as by default @SpringBootTest will load all beans defined in your applications which may be too much for testing (see this for details) :

@SpringBootTest
public class MongoPropertiesTest {

    @Autowired
    private  MongoProperties properties;

    @Configuration
    @EnableConfigurationProperties({MongoProperties.class})
    public static class Config {

    }
}

If you really want to just use @ExtendWith(SpringExtension.class) , you will lose the spring-boot feature such as externalising configuration features which cause you cannot load properties from application.properties and cannot support loading properties from YAML file etc. You have to manually configure ConfigDataApplicationContextInitializer to enable such features :

@ExtendWith(SpringExtension.class)
@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class)
public class MongoPropertiesTest {
    
    @Autowired
    private MongoProperties properties;

    @Configuration
    @EnableConfigurationProperties({MongoProperties.class})
    public static class Config {

    }

}

You can consider to further use @SpringJUnitConfig to combine @ExtendWith(SpringExtension.class) and @ContextConfiguration together which gives you :

@SpringJUnitConfig(initializers = ConfigDataApplicationContextInitializer.class)
public class MongoPropertiesTest {
    
    @Autowired
    private MongoProperties properties;

    @Configuration
    @EnableConfigurationProperties({MongoProperties.class})
    public static class Config {

    }
}

Actually both approaches do not have much differences in term of speed , so I prefer to just use @SpringBootTest for simplicity as it does not requires you to configure ConfigDataApplicationContextInitializer.

Upvotes: 15

Related Questions