mardi 29 mars 2016

When running test class, properties can't be read properly from .properties file by using @Value annotation, in Spring Maven project

I am working on this issue for days, I am writing unit test for a serviceClass.The serviceClass is like below :

import ...
@Component
public class ServiceClass implements ServiceInterface {
    @Value("${data.layer.url}")
    private String  dataLayerUrl;

    @Autowired
    private RestTemplate restTemplate

    public void dummy(){
        restTemplate.postForObject(dataLayerUrl + "/" + ... , ...);
    }

}

And CONFIG_DIR is already defined in application configuration file.

I have a SomeConfig class defining beans as below. (http://...src/main/java/com.app/configuration/SomeConfig)

@Configuration
@ComponentScan(basePackages = {"..."})
@PropertySource(value = "file:${CONFIG_DIR}/app.properties")
public class SomeConfig{

    @Bean
    public RestTemplate restTemplate() {

            RestTemplate restTemplate = new RestTemplate();
            ...
            return restTemplate;
    }
}

My test class is as below:

Import ...
@Profile("test")
public class ServiceClassTest extends AbstractTest {
     @Value("${data.layer.url}")
     private String  dataLayerUrl;

     @InjectMocks
     private ServiceClass ServiceClass;
     @Mock
     RestTemplate restTemplate;
     @Before
     public void initializeMockito() {
         MockitoAnnotations.initMocks(this);
     }    
     @Test
     public void dummyTest(){
         when(restTemplate.postForObject(dataLayerUrl + "/" + ..., ...)).thenReturn(...);
         serviceClass.dummy();

         assertEquals(...);
         verify(restTemplate).postForObject(...);
     }
}

And then my AbstractTest as below :

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@SpringApplicationConfiguration(classes = Application.class)
@ContextConfiguration(classes = {TestConfiguration.class})
@ComponentScan(basePackages = ...)
public abstract class AbstractTest {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
}

And I also have .../src/test/resources/application-test.properties defined as below

#Datalayer properties
data.layer.url=http://ift.tt/1LXPDrY

This is the same as defined in application.properties(which locates outside of project in CONFIG_DIR.

The logic of testing is just to make sure when you call dummy method of serviceClass, the postForObject method of restTemplate is called exactly once.

But when doing it this way, I am facing with 2 problems. when I run test class in debug mode, I found

  1. in ServiceClassTest. dataLayerUrl = "$data.layer.url"

  2. in ServiceClass. dataLayerUrl = null

I researched around and be able to solve problem one by following this link http://ift.tt/1pIxjIT

But this is not an ideal way to do this, since by default spring should be able to read properties from application-test.properties. And I never figured out what caused the second issue and how to solve it.

I think this would be a common issue when writing unit test on class which read properties from .properties file using $Value annotation. Any comments or suggestions would be very much appreciated.

Aucun commentaire:

Enregistrer un commentaire