Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populating Spring @Value during Unit Test

I'm trying to write a Unit Test for a simple bean that's used in my program to validate forms. The bean is annotated with @Component and has a class variable that is initialized using

@Value("${this.property.value}") private String thisProperty; 

I would like to write unit tests for the validation methods inside this class, however, if possible I would like to do so without utilizing the properties file. My reasoning behind this, is that if the value I'm pulling from the properties file changes, I would like that to not affect my test case. My test case is testing the code that validates the value, not the value itself.

Is there a way to use Java code inside my test class to initialize a Java class and populate the Spring @Value property inside that class then use that to test with?

I did find this How To that seems to be close, but still uses a properties file. I would rather it all be Java code.

like image 973
Kyle Avatar asked Jun 27 '13 21:06

Kyle


People also ask

What does @value mean in spring?

@Value spring boot annotation is used to inject values from the properties file into the java variables that have been configured. The @Value annotation in spring boot is used to assign values to variables and method parameters from properties files or system environments.

What does @value annotation do in spring boot?

Spring @Value annotation is used to assign default values to variables and method arguments. We can read spring environment variables as well as system variables using @Value annotation.

Can I use @value in pojo?

For the record, the specification of what a POJO is, means that the class cannot contain pre-specified annotations. So even in another world where @Value could work on a non-spring bean, it would still, by definition, break the POJO aspect of the class.

Can we use @value inside a method?

no :) you can use annotations to annotate classes, fields, methods and their arguments. but not in methods, since there is no way, to get method- local variables using reflection in order to process these annotations. Use @Value in your field, and read the value from your method.


2 Answers

If possible I would try to write those test without Spring Context. If you create this class in your test without spring, then you have full control over its fields.

To set the @value field you can use Springs ReflectionTestUtils - it has a method setField to set private fields.

@see JavaDoc: ReflectionTestUtils.setField(java.lang.Object, java.lang.String, java.lang.Object)

like image 147
Ralph Avatar answered Sep 18 '22 11:09

Ralph


Since Spring 4.1 you could set up property values just in code by using org.springframework.test.context.TestPropertySource annotation on Unit Tests class level. You could use this approach even for injecting properties into dependent bean instances

For example

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = FooTest.Config.class) @TestPropertySource(properties = {     "some.bar.value=testValue", }) public class FooTest {    @Value("${some.bar.value}")   String bar;    @Test   public void testValueSetup() {     assertEquals("testValue", bar);   }     @Configuration   static class Config {      @Bean     public static PropertySourcesPlaceholderConfigurer propertiesResolver() {         return new PropertySourcesPlaceholderConfigurer();     }    }  } 

Note: It's necessary to have instance of org.springframework.context.support.PropertySourcesPlaceholderConfigurer in Spring context

Edit 24-08-2017: If you are using SpringBoot 1.4.0 and later you could initialize tests with @SpringBootTest and @SpringBootConfiguration annotations. More info here

In case of SpringBoot we have following code

@SpringBootTest @SpringBootConfiguration @RunWith(SpringJUnit4ClassRunner.class) @TestPropertySource(properties = {     "some.bar.value=testValue", }) public class FooTest {    @Value("${some.bar.value}")   String bar;    @Test   public void testValueSetup() {     assertEquals("testValue", bar);   }  } 
like image 28
Dmytro Boichenko Avatar answered Sep 16 '22 11:09

Dmytro Boichenko