'How to initialize variables with @Value in Junit

This is the class I need to test:

public class AConfiguration {
    @Value("classpath:abc.properties")
    private Resource aFile
    
    @Bean
    public void task() throws IOException {
        Properties properties = new Properties();
        properties.load(aFile.getInputStream());
    }
}

this is Junit test code

@Test
public void testTask() {
    AConfiguration ac = new AConfiguration();
    ac.task();
}

aFile is expected to be initialized with @Value annotation, but it is null when unittest is running to that line.

Thank you.



Solution 1:[1]

@Value belongs to the "spring world". Its used by spring to inject things.

Your unit test on the other hand doesn't even use spring, instead there is an explicit call to new AConfiguration. This way nobody processes the @Value annotation.

So you have two different directions that depend on what / how do you want to test the code.

Direction 1

Keep test as simple as possible and load the properties from the memory or by yourself.

This means that you won't need spring at all, probably you'll split the "Configuration" object from the actual business object that has a "business" method task and your test will call the task and won't even create a AConfiguration object.

Direction 2

Run spring during the test. This is good for integration tests, but you'll be able to load configurations in the same way the Spring does during its startup. This topic by itself it too broad to be discussed "in general" IMO. Start with SpringExtension and @ContextConfiguration annotation.

Which direction to prefer? Well, its hard to tell without knowing what are you doing exactly, but as a rule of thumb, the unit tests (those without spring) are way more lightweight and easier to write, run and maintain in a real-life project.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mark Bramnik