Nikhil Das Nomula
Nikhil Das Nomula

Reputation: 1953

Spring jUnit Testing properties file

I have a jUnit Test that has its own properties file(application-test.properties) and its spring config file(application-core-test.xml).

One of the method uses an object instantiated by spring config and that is a spring component. One of the members in the classes derives its value from application.properties which is our main properties file. While accessing this value through jUnit it is always null. I even tried changing the properties file to point to the actual properties file, but that doesnt seem to work.

Here is how I am accessing the properties file object

@Component
@PropertySource("classpath:application.properties")
public abstract class A {

    @Value("${test.value}")
    public String value;

    public A(){
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

    public A(String text) {
        this();
        // do something with text and value.. here is where I run into NPE
    }

}

public class B extends A { 
     //addtnl code

    private B() {

    }


    private B(String text) {
         super(text)
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:META-INF/spring/application-core-test.xml",
                             "classpath:META-INF/spring/application-schedule-test.xml"})
@PropertySource("classpath:application-test.properties")
public class TestD {

    @Value("${value.works}")
    public String valueWorks;

    @Test
    public void testBlah() {     
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        B b= new B("blah");
        //...addtnl code

    }    
}      

Upvotes: 36

Views: 202354

Answers (7)

Tapan Upadhyay
Tapan Upadhyay

Reputation: 101

If you want to load a few properties, I found a good way in the spring ReflectionTestUtils:

@Before
Public void setup(){
 ReflectionTestUtils.setField(youclassobject, "value", "yourValue")
 
}

You can follow this link as well for more details https://roytuts.com/mock-an-autowired-value-field-in-spring-with-junit-mockito/

Upvotes: 3

Robert Moskal
Robert Moskal

Reputation: 22553

Firstly, application.properties in the @PropertySource should read application-test.properties if that's what the file is named (matching these things up matters):

@PropertySource("classpath:application-test.properties")

That file should be under your /src/test/resources classpath (at the root).

I don't understand why you'd specify a dependency hard coded to a file called application-test.properties. Is that component only to be used in the test environment?

The normal thing to do is to have property files with the same name on different classpaths. You load one or the other depending on whether you are running your tests or not.

In a typically laid out application, you'd have:

src/test/resources/application.properties

and

src/main/resources/application.properties

And then inject it like this:

@PropertySource("classpath:application.properties")

The even better thing to do would be to expose that property file as a bean in your spring context and then inject that bean into any component that needs it. This way your code is not littered with references to application.properties and you can use anything you want as a source of properties. Here's an example: how to read properties file in spring project?

Upvotes: 43

ACV
ACV

Reputation: 10562

The answer to your question is that @PropertySource("classpath:application-test.properties") does not work outside of spring boot test. Only when you have @SpringBootTest only then this works and properties are automatically injected.

Upvotes: -1

Om Prakash N
Om Prakash N

Reputation: 149

How to read values from properties file while running JUnit Test ? ReflectionTestUtils is the simplest way to set values for any variable that is reading values from properties file.

Inside the setup function, add the below line:

ReflectionTestUtils.setField(ObjectName, "VariableToSetValue", "Value");

Eg: ReflectionTestUtils.setField(studentService, "uri", "http://example.com");

Upvotes: 1

loud_mouth
loud_mouth

Reputation: 23

If you are using a jar file inside a docker container, and the resource properties file, say application.properties is packaged within the same classes directory that contains the java(this is what IntelliJ IDE does automatically for resources file stored in /src/main/resources), this is what helped me:

public static Properties props = new Properties();

    static {
        try {
            props.load(
                    Thread
                            .currentThread()
                            .getContextClassLoader()
                            .getResourceAsStream("application.properties")
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Most other methods either only worked inside the IDE or inside the Docker. This one works in both.

Upvotes: 1

Siena
Siena

Reputation: 777

I faced the same issue, spent too much calories searching for the right fix until I decided to settle down with file reading:

Properties configProps = new Properties();
InputStream iStream = new ClassPathResource("myapp-test.properties").getInputStream();
InputStream iStream = getConfigFile();
configProps.load(iStream);

Upvotes: 4

sendon1982
sendon1982

Reputation: 11234

As for the testing, you should use from Spring 4.1 which will overwrite the properties defined in other places:

@TestPropertySource("classpath:application-test.properties")

Test property sources have higher precedence than those loaded from the operating system's environment or Java system properties as well as property sources added by the application like @PropertySource

Upvotes: 33

Related Questions