Search code examples
javaspring-bootjunit

Junit test class for dependency with value from application.properties


I am writing Junit test case for the following class :

@Component
public class ExpandParam {

    /* expand parameter with value "expand" */
    @Value("${api.expand.value}")
    private String expandParam;
    
    public MultiValueMap<String, String> getExpandQueryParam(String[] expand) {
        
        MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
        
        // Creating comma separated format string
        StringBuilder builder = new StringBuilder();
        for (String value : expand) {
            if(!expand[expand.length-1].equals(value)) {
                builder.append(value+", ");
            }
            else {
                builder.append(value);
            }
        }
        String expandText = builder.toString();
        queryParams.add(expandParam, expandText);
        
        return queryParams;
    }
}

The test class is following :

public class ExpandParamTest {

    @InjectMocks
    @Spy
    ExpandParam expandQueryParam;
    
//  @Value("${api.expand.value}")
//  private String expandParam;
    
    private String[] expand = {"fees"};
    
    @Before
    public void setup() {
        ReflectionTestUtils.setField(expandQueryParam, "expandParam", "expand");
        
    }
    
    @Test
    public void testExpandParam() {
        MultiValueMap<String, String> queryParams = expandQueryParam.getExpandQueryParam(expand);
        
        try {
            System.out.println(new ObjectMapper().writeValueAsString(queryParams));
        } catch (JsonProcessingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

In application. properties files I have set the values :

#expand param
api.expand.value: expand

I am new to this, can any one tell me where I am making the mistake: Getting the following error:

java.lang.IllegalArgumentException: Either targetObject or targetClass for the field must be specified at org.springframework.util.Assert.isTrue(Assert.java:121) at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:178) at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:107) at org.springframework.test.util.ReflectionTestUtils.setField(ReflectionTestUtils.java:91) at com.aig.rs.products.orchestrator.api.utils.ExpandParamTest.setup(ExpandParamTest.java:29)


Solution

  • @Value is a spring annotation, it depends on the Spring Context to function. If you want @Value to read the value from your application properties then you need to convert your unit test into a @SpringBootTest. Take a look at this tutorial to understand a bit more about Spring Test.

    You're also using ReflectionTestUtils.setField(expandQueryParam, "expandParam", "expand"); which will just set a value to this field, not read it from properties. This exception you're seeing is because expandQueryParam is null, these annotations @Spy and @InjectMocks are Mockito annotations and for them to initialize your object you need to enable mockito annotations, you can do this by adding @ExtendWith(MockitoExtension.class) on top of your class or using MockitoAnnotations.initMocks(this) in setUp method.

    I don't think you need mockito to test this class, in my opinion going for a Spring Test would be a better option this way you can also test the reading of the property key.